Merge "Allow passing the bitmap to ContentSuggestionsService via the extras Bundle"
diff --git a/Android.bp b/Android.bp
index 0547481..8169d6d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -194,13 +194,14 @@
         ":framework-core-sources",
         ":framework-drm-sources",
         ":framework-graphics-sources",
+        ":framework-jobscheduler-sources", // jobscheduler is not a module for R
         ":framework-keystore-sources",
         ":framework-location-sources",
         ":framework-lowpan-sources",
-        ":framework-media-sources",
         ":framework-mca-effect-sources",
         ":framework-mca-filterfw-sources",
         ":framework-mca-filterpacks-sources",
+        ":framework-media-sources",
         ":framework-mime-sources",
         ":framework-mms-sources",
         ":framework-opengl-sources",
@@ -213,6 +214,9 @@
         ":PacProcessor-aidl-sources",
         ":ProxyHandler-aidl-sources",
 
+        // AIDL from frameworks/base/native/
+        ":platform-compat-native-aidl",
+
         // AIDL sources from external directories
         ":dumpstate_aidl",
         ":framework_native_aidl",
@@ -407,7 +411,6 @@
     installable: true,
     static_libs: [
         "framework-minus-apex",
-        "jobscheduler-framework",
     ],
     required: [
         "framework-platform-compat-config",
@@ -545,6 +548,12 @@
     ],
 }
 
+filegroup {
+    name: "framework-tethering-shared-srcs",
+    srcs: [
+        "core/java/android/util/LocalLog.java",
+    ],
+}
 // Build ext.jar
 // ============================================================
 java_library {
@@ -919,7 +928,8 @@
     "--hide RequiresPermission " +
     "--hide MissingPermission --hide BroadcastBehavior " +
     "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
-    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo "
+    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
+    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
 
 // http://b/129765390 Rewrite links to "platform" or "technotes" folders
 // which are siblings (and thus outside of) {@docRoot}.
@@ -962,7 +972,6 @@
         ":updatable-media-srcs",
         "test-mock/src/**/*.java",
         "test-runner/src/**/*.java",
-        ":jobscheduler-framework-source",
     ],
     libs: framework_docs_only_libs,
     local_sourcepaths: frameworks_base_subdirs,
@@ -1025,7 +1034,6 @@
         ":core-current-stubs-source",
         ":core_public_api_files",
         ":updatable-media-srcs",
-        ":jobscheduler-framework-source",
     ],
     libs: ["framework-internal-utils"],
     local_sourcepaths: frameworks_base_subdirs,
@@ -1052,6 +1060,7 @@
         "core/res/AndroidManifest.xml",
     ],
     args: metalava_framework_docs_args,
+    write_sdk_values: true,
 }
 
 droidstubs {
@@ -1061,6 +1070,7 @@
         "core/res/AndroidManifest.xml",
     ],
     args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi ",
+    write_sdk_values: true,
 }
 
 droiddoc {
@@ -1084,7 +1094,6 @@
     ],
     proofread_file: "offline-sdk-docs-proofrerad.txt",
     args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
-    write_sdk_values: true,
     static_doc_index_redirect: "docs/docs-preview-index.html",
 }
 
@@ -1102,7 +1111,6 @@
     ],
     proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
     args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
-    write_sdk_values: true,
     static_doc_index_redirect: "docs/docs-documentation-redirect.html",
     static_doc_properties: "docs/source.properties",
 }
@@ -1122,7 +1130,6 @@
     proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
     args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
     " -offlinemode -title \"Android System SDK\" -referenceonly",
-    write_sdk_values: true,
     static_doc_index_redirect: "docs/docs-documentation-redirect.html",
     static_doc_properties: "docs/source.properties",
 }
@@ -1597,3 +1604,35 @@
         "core/java/com/android/internal/util/StateMachine.java",
     ],
 }
+
+filegroup {
+    name: "framework-ims-common-shared-srcs",
+    srcs: [
+        "core/java/android/os/AsyncResult.java",
+        "core/java/android/os/RegistrantList.java",
+        "core/java/android/os/Registrant.java",
+        "core/java/com/android/internal/os/SomeArgs.java",
+        "core/java/com/android/internal/util/Preconditions.java",
+    ],
+}
+
+filegroup {
+    name: "framework-wifistack-shared-srcs",
+    srcs: [
+        ":framework-annotations",
+        "core/java/android/util/KeyValueListParser.java",
+        "core/java/android/util/LocalLog.java",
+        "core/java/android/util/Rational.java",
+        "core/java/android/util/proto/ProtoStream.java",
+        "core/java/android/util/proto/ProtoOutputStream.java",
+        "core/java/com/android/internal/util/FastXmlSerializer.java",
+        "core/java/com/android/internal/util/HexDump.java",
+        "core/java/com/android/internal/util/IState.java",
+        "core/java/com/android/internal/util/MessageUtils.java",
+        "core/java/com/android/internal/util/Preconditions.java",
+        "core/java/com/android/internal/util/State.java",
+        "core/java/com/android/internal/util/StateMachine.java",
+        "core/java/com/android/internal/util/WakeupMessage.java",
+        "core/java/com/android/internal/util/XmlUtils.java",
+    ],
+}
diff --git a/Android.mk b/Android.mk
index 9bda2dc..815a169 100644
--- a/Android.mk
+++ b/Android.mk
@@ -54,6 +54,24 @@
 .PHONY: docs offline-sdk-docs
 docs offline-sdk-docs: $(OUT_DOCS)/offline-sdk-timestamp
 
+SDK_METADATA_DIR :=$= $(call intermediates-dir-for,PACKAGING,framework-doc-stubs-metadata,,COMMON)
+SDK_METADATA_FILES :=$= $(addprefix $(SDK_METADATA_DIR)/,\
+    activity_actions.txt \
+    broadcast_actions.txt \
+    categories.txt \
+    features.txt \
+    service_actions.txt \
+    widgets.txt)
+SDK_METADATA :=$= $(firstword $(SDK_METADATA_FILES))
+$(SDK_METADATA): .KATI_IMPLICIT_OUTPUTS := $(filter-out $(SDK_METADATA),$(SDK_METADATA_FILES))
+$(SDK_METADATA): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/framework-doc-stubs-metadata.zip
+	rm -rf $(SDK_METADATA_DIR)
+	mkdir -p $(SDK_METADATA_DIR)
+	unzip -qo $< -d $(SDK_METADATA_DIR)
+
+.PHONY: framework-doc-stubs
+framework-doc-stubs: $(SDK_METADATA)
+
 # Run this for checkbuild
 checkbuild: doc-comment-check-docs
 
diff --git a/apct-tests/perftests/autofill/AndroidManifest.xml b/apct-tests/perftests/autofill/AndroidManifest.xml
index 9c8abc3..1e3532b 100644
--- a/apct-tests/perftests/autofill/AndroidManifest.xml
+++ b/apct-tests/perftests/autofill/AndroidManifest.xml
@@ -18,7 +18,7 @@
 
     <application>
         <uses-library android:name="android.test.runner" />
-        <activity android:name="android.perftests.utils.StubActivity">
+        <activity android:name="android.perftests.utils.PerfTestActivity">
           <intent-filter>
             <action android:name="com.android.perftests.core.PERFTEST" />
           </intent-filter>
diff --git a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
index 3aa6749..236f548 100644
--- a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
@@ -38,7 +38,8 @@
     private static final String PERMISSION_NAME_DOESNT_EXIST =
             "com.android.perftests.core.TestBadPermission";
     private static final ComponentName TEST_ACTIVITY =
-            new ComponentName("com.android.perftests.core", "android.perftests.utils.StubActivity");
+            new ComponentName("com.android.perftests.core",
+                    "android.perftests.utils.PerfTestActivity");
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
index 621ff9a..3902aa2 100644
--- a/apex/jobscheduler/framework/Android.bp
+++ b/apex/jobscheduler/framework/Android.bp
@@ -1,5 +1,5 @@
 filegroup {
-    name: "jobscheduler-framework-source",
+    name: "framework-jobscheduler-sources",
     srcs: [
         "java/**/*.java",
         "java/android/app/job/IJobCallback.aidl",
@@ -12,13 +12,12 @@
 
 java_library {
     name: "jobscheduler-framework",
-    installable: true,
+    installable: false,
+    compile_dex: true,
     sdk_version: "core_platform",
-
     srcs: [
-        ":jobscheduler-framework-source",
+        ":framework-jobscheduler-sources",
     ],
-
     aidl: {
         export_include_dirs: [
             "java",
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index 3cfb080..041825c 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -1,9 +1,9 @@
 package com.android.server.usage;
 
+import android.annotation.UserIdInt;
 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;
 
@@ -33,9 +33,25 @@
         }
     }
 
-    void onBootPhase(int phase);
+    /**
+     * Listener interface for notifications that an app's idle state changed.
+     */
+    abstract static class AppIdleStateChangeListener {
 
-    boolean isParoledOrCharging();
+        /** Callback to inform listeners that the idle state has changed to a new bucket. */
+        public abstract void onAppIdleStateChanged(String packageName, @UserIdInt int userId,
+                boolean idle, int bucket, int reason);
+
+        /**
+         * Optional callback to inform the listener that the app has transitioned into
+         * an active state due to user interaction.
+         */
+        public void onUserInteractionStarted(String packageName, @UserIdInt int userId) {
+            // No-op by default
+        }
+    }
+
+    void onBootPhase(int phase);
 
     void postCheckIdleStates(int userId);
 
@@ -59,13 +75,15 @@
 
     int getAppId(String packageName);
 
-    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+    /**
+     * @see #isAppIdleFiltered(String, int, int, long)
+     */
+    boolean isAppIdleFiltered(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,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 14d5a68..a1734d8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -37,7 +37,6 @@
 import android.app.job.JobWorkItem;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
-import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -103,6 +102,8 @@
 import com.android.server.job.controllers.TimeController;
 import com.android.server.job.restrictions.JobRestriction;
 import com.android.server.job.restrictions.ThermalStatusRestriction;
+import com.android.server.usage.AppStandbyInternal;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import libcore.util.EmptyArray;
 
@@ -266,11 +267,6 @@
     boolean mReportedActive;
 
     /**
-     * Are we currently in device-wide standby parole?
-     */
-    volatile boolean mInParole;
-
-    /**
      * A mapping of which uids are currently in the foreground to their effective priority.
      */
     final SparseIntArray mUidPriorityOverride = new SparseIntArray();
@@ -1300,7 +1296,9 @@
         // Set up the app standby bucketing tracker
         mStandbyTracker = new StandbyTracker();
         mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
-        mUsageStats.addAppIdleStateChangeListener(mStandbyTracker);
+
+        AppStandbyInternal appStandby = LocalServices.getService(AppStandbyInternal.class);
+        appStandby.addListener(mStandbyTracker);
 
         // The job store needs to call back
         publishLocalService(JobSchedulerInternal.class, new LocalService());
@@ -2361,14 +2359,6 @@
         }
 
         @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            if (DEBUG_STANDBY) {
-                Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
-            }
-            mInParole = isParoleOn;
-        }
-
-        @Override
         public void onUserInteractionStarted(String packageName, int userId) {
             final int uid = mLocalPM.getPackageUid(packageName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
@@ -3031,10 +3021,6 @@
             }
             pw.println();
 
-            pw.print("    In parole?: ");
-            pw.print(mInParole);
-            pw.println();
-
             for (int i = mJobRestrictions.size() - 1; i >= 0; i--) {
                 pw.print("    ");
                 mJobRestrictions.get(i).dumpConstants(pw);
@@ -3222,7 +3208,6 @@
             }
             proto.end(settingsToken);
 
-            proto.write(JobSchedulerServiceDumpProto.IN_PAROLE, mInParole);
             for (int i = mJobRestrictions.size() - 1; i >= 0; i--) {
                 mJobRestrictions.get(i).dumpConstants(proto);
             }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 400d902..cda5244 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -35,8 +35,6 @@
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.IUidObserver;
-import android.app.usage.UsageStatsManagerInternal;
-import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -70,6 +68,8 @@
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobServiceContext;
 import com.android.server.job.StateControllerProto;
+import com.android.server.usage.AppStandbyInternal;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -414,8 +414,6 @@
     private final Handler mHandler;
     private final QcConstants mQcConstants;
 
-    private volatile boolean mInParole;
-
     /** How much time each app will have to run jobs within their standby bucket window. */
     private long mAllowedTimePerPeriodMs = QcConstants.DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
 
@@ -576,9 +574,8 @@
         mContext.registerReceiverAsUser(mPackageAddedReceiver, UserHandle.ALL, filter, null, null);
 
         // Set up the app standby bucketing tracker
-        UsageStatsManagerInternal usageStats = LocalServices.getService(
-                UsageStatsManagerInternal.class);
-        usageStats.addAppIdleStateChangeListener(new StandbyTracker());
+        AppStandbyInternal appStandby = LocalServices.getService(AppStandbyInternal.class);
+        appStandby.addListener(new StandbyTracker());
 
         try {
             ActivityManager.getService().registerUidObserver(mUidObserver,
@@ -711,7 +708,6 @@
     public long getMaxJobExecutionTimeMsLocked(@NonNull final JobStatus jobStatus) {
         // If quota is currently "free", then the job can run for the full amount of time.
         if (mChargeTracker.isCharging()
-                || mInParole
                 || isTopStartedJobLocked(jobStatus)
                 || isUidInForeground(jobStatus.getSourceUid())) {
             return JobServiceContext.EXECUTING_TIMESLICE_MILLIS;
@@ -737,8 +733,8 @@
             final int standbyBucket) {
         if (standbyBucket == NEVER_INDEX) return false;
 
-        // Quota constraint is not enforced while charging or when parole is on.
-        if (mChargeTracker.isCharging() || mInParole) {
+        // Quota constraint is not enforced while charging.
+        if (mChargeTracker.isCharging()) {
             return true;
         }
 
@@ -1780,20 +1776,6 @@
                 }
             });
         }
-
-        @Override
-        public void onParoleStateChanged(final boolean isParoleOn) {
-            mInParole = isParoleOn;
-            if (DEBUG) {
-                Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
-            }
-            // Update job bookkeeping out of band.
-            BackgroundThread.getHandler().post(() -> {
-                synchronized (mLock) {
-                    maybeUpdateAllConstraintsLocked();
-                }
-            });
-        }
     }
 
     private final class DeleteTimingSessionsFunctor implements Consumer<List<TimingSession>> {
@@ -2515,7 +2497,6 @@
     public void dumpControllerStateLocked(final IndentingPrintWriter pw,
             final Predicate<JobStatus> predicate) {
         pw.println("Is charging: " + mChargeTracker.isCharging());
-        pw.println("In parole: " + mInParole);
         pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
         pw.println();
 
@@ -2639,7 +2620,6 @@
         final long mToken = proto.start(StateControllerProto.QUOTA);
 
         proto.write(StateControllerProto.QuotaController.IS_CHARGING, mChargeTracker.isCharging());
-        proto.write(StateControllerProto.QuotaController.IS_IN_PAROLE, mInParole);
         proto.write(StateControllerProto.QuotaController.ELAPSED_REALTIME,
                 sElapsedRealtimeClock.millis());
 
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 7c472a9..bcd8be7 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -45,7 +45,6 @@
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
 
-import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
 import android.annotation.UserIdInt;
@@ -54,7 +53,6 @@
 import android.app.usage.AppStandbyInfo;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManager.StandbyBuckets;
-import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.appwidget.AppWidgetManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -70,10 +68,8 @@
 import android.hardware.display.DisplayManager;
 import android.net.ConnectivityManager;
 import android.net.Network;
-import android.net.NetworkInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkScoreManager;
-import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Environment;
 import android.os.Handler;
@@ -105,6 +101,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.usage.AppIdleHistory.AppUsageHistory;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import java.io.File;
 import java.io.PrintWriter;
@@ -192,21 +189,14 @@
     static final int MSG_INFORM_LISTENERS = 3;
     static final int MSG_FORCE_IDLE_STATE = 4;
     static final int MSG_CHECK_IDLE_STATES = 5;
-    static final int MSG_CHECK_PAROLE_TIMEOUT = 6;
-    static final int MSG_PAROLE_END_TIMEOUT = 7;
     static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
-    static final int MSG_PAROLE_STATE_CHANGED = 9;
     static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
     /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
     static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
     static final int MSG_REPORT_SYNC_SCHEDULED = 12;
     static final int MSG_REPORT_EXEMPTED_SYNC_START = 13;
-    static final int MSG_UPDATE_STABLE_CHARGING= 14;
 
     long mCheckIdleIntervalMillis;
-    long mAppIdleParoleIntervalMillis;
-    long mAppIdleParoleWindowMillis;
-    long mAppIdleParoleDurationMillis;
     long[] mAppStandbyScreenThresholds = SCREEN_TIME_THRESHOLDS;
     long[] mAppStandbyElapsedThresholds = ELAPSED_TIME_THRESHOLDS;
     /** Minimum time a strong usage event should keep the bucket elevated. */
@@ -244,20 +234,12 @@
      * start is the first usage of the app
      */
     long mInitialForegroundServiceStartTimeoutMillis;
-    /** The length of time phone must be charging before considered stable enough to run jobs  */
-    long mStableChargingThresholdMillis;
 
     private volatile boolean mAppIdleEnabled;
-    boolean mAppIdleTempParoled;
-    boolean mCharging;
-    boolean mChargingStable;
-    private long mLastAppIdleParoledTime;
     private boolean mSystemServicesReady = false;
     // There was a system update, defaults need to be initialized after services are ready
     private boolean mPendingInitializeDefaults;
 
-    private final DeviceStateReceiver mDeviceStateReceiver;
-
     private volatile boolean mPendingOneTimeCheckIdleStates;
 
     private final AppStandbyHandler mHandler;
@@ -267,7 +249,6 @@
 
     private AppWidgetManager mAppWidgetManager;
     private ConnectivityManager mConnectivityManager;
-    private PowerManager mPowerManager;
     private PackageManager mPackageManager;
     Injector mInjector;
 
@@ -329,12 +310,6 @@
         mContext = mInjector.getContext();
         mHandler = new AppStandbyHandler(mInjector.getLooper());
         mPackageManager = mContext.getPackageManager();
-        mDeviceStateReceiver = new DeviceStateReceiver();
-
-        IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING);
-        deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
-        deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
-        mContext.registerReceiver(mDeviceStateReceiver, deviceStates);
 
         synchronized (mAppIdleLock) {
             mAppIdleHistory = new AppIdleHistory(mInjector.getDataSystemDirectory(),
@@ -353,15 +328,7 @@
 
     @VisibleForTesting
     void setAppIdleEnabled(boolean enabled) {
-        synchronized (mAppIdleLock) {
-            if (mAppIdleEnabled != enabled) {
-                final boolean oldParoleState = isParoledOrCharging();
-                mAppIdleEnabled = enabled;
-                if (isParoledOrCharging() != oldParoleState) {
-                    postParoleStateChanged();
-                }
-            }
-        }
+        mAppIdleEnabled = enabled;
     }
 
     @Override
@@ -381,7 +348,6 @@
 
             mAppWidgetManager = mContext.getSystemService(AppWidgetManager.class);
             mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
-            mPowerManager = mContext.getSystemService(PowerManager.class);
 
             mInjector.registerDisplayListener(mDisplayListener, mHandler);
             synchronized (mAppIdleLock) {
@@ -402,8 +368,6 @@
             if (mPendingOneTimeCheckIdleStates) {
                 postOneTimeCheckIdleStates();
             }
-        } else if (phase == PHASE_BOOT_COMPLETED) {
-            setChargingState(mInjector.isCharging());
         }
     }
 
@@ -504,93 +468,6 @@
         }
     }
 
-    @VisibleForTesting
-    void setChargingState(boolean charging) {
-        synchronized (mAppIdleLock) {
-            if (mCharging != charging) {
-                mCharging = charging;
-                if (DEBUG) Slog.d(TAG, "Setting mCharging to " + charging);
-                if (charging) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "Scheduling MSG_UPDATE_STABLE_CHARGING  delay = "
-                                + mStableChargingThresholdMillis);
-                    }
-                    mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STABLE_CHARGING,
-                            mStableChargingThresholdMillis);
-                } else {
-                    mHandler.removeMessages(MSG_UPDATE_STABLE_CHARGING);
-                    updateChargingStableState();
-                }
-            }
-        }
-    }
-
-    private void updateChargingStableState() {
-        synchronized (mAppIdleLock) {
-            if (mChargingStable != mCharging) {
-                if (DEBUG) Slog.d(TAG, "Setting mChargingStable to " + mCharging);
-                mChargingStable = mCharging;
-                postParoleStateChanged();
-            }
-        }
-    }
-
-    private void setAppIdleParoled(boolean paroled) {
-        synchronized (mAppIdleLock) {
-            final long now = mInjector.currentTimeMillis();
-            if (mAppIdleTempParoled != paroled) {
-                mAppIdleTempParoled = paroled;
-                if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
-                if (paroled) {
-                    postParoleEndTimeout();
-                } else {
-                    mLastAppIdleParoledTime = now;
-                    postNextParoleTimeout(now, false);
-                }
-                postParoleStateChanged();
-            }
-        }
-    }
-
-    @Override
-    public boolean isParoledOrCharging() {
-        if (!mAppIdleEnabled) return true;
-        synchronized (mAppIdleLock) {
-            // Only consider stable charging when determining charge state.
-            return mAppIdleTempParoled || mChargingStable;
-        }
-    }
-
-    private void postNextParoleTimeout(long now, boolean forced) {
-        if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
-        mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
-        // Compute when the next parole needs to happen. We check more frequently than necessary
-        // since the message handler delays are based on elapsedRealTime and not wallclock time.
-        // The comparison is done in wallclock time.
-        long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) - now;
-        if (forced) {
-            // Set next timeout for the end of the parole window
-            // If parole is not set by the end of the window it will be forced
-            timeLeft += mAppIdleParoleWindowMillis;
-        }
-        if (timeLeft < 0) {
-            timeLeft = 0;
-        }
-        mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft);
-    }
-
-    private void postParoleEndTimeout() {
-        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT");
-        mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT);
-        mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis);
-    }
-
-    private void postParoleStateChanged() {
-        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED");
-        mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED);
-        mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
-    }
-
     @Override
     public void postCheckIdleStates(int userId) {
         mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
@@ -787,48 +664,6 @@
         return THRESHOLD_BUCKETS[bucketIndex];
     }
 
-    private void checkParoleTimeout() {
-        boolean setParoled = false;
-        boolean waitForNetwork = false;
-        NetworkInfo activeNetwork = mConnectivityManager.getActiveNetworkInfo();
-        boolean networkActive = activeNetwork != null &&
-                activeNetwork.isConnected();
-
-        synchronized (mAppIdleLock) {
-            final long now = mInjector.currentTimeMillis();
-            if (!mAppIdleTempParoled) {
-                final long timeSinceLastParole = now - mLastAppIdleParoledTime;
-                if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
-                    if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
-                    if (networkActive) {
-                        // If network is active set parole
-                        setParoled = true;
-                    } else {
-                        if (timeSinceLastParole
-                                > mAppIdleParoleIntervalMillis + mAppIdleParoleWindowMillis) {
-                            if (DEBUG) Slog.d(TAG, "Crossed end of parole window, force parole");
-                            setParoled = true;
-                        } else {
-                            if (DEBUG) Slog.d(TAG, "Network unavailable, delaying parole");
-                            waitForNetwork = true;
-                            postNextParoleTimeout(now, true);
-                        }
-                    }
-                } else {
-                    if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
-                    postNextParoleTimeout(now, false);
-                }
-            }
-        }
-        if (waitForNetwork) {
-            mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
-        }
-        if (setParoled) {
-            // Set parole if network is available
-            setAppIdleParoled(true);
-        }
-    }
-
     private void notifyBatteryStats(String packageName, int userId, boolean idle) {
         try {
             final int uid = mPackageManager.getPackageUidAsUser(packageName,
@@ -844,30 +679,6 @@
         }
     }
 
-    private void onDeviceIdleModeChanged() {
-        final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
-        if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
-        boolean paroled = false;
-        synchronized (mAppIdleLock) {
-            final long timeSinceLastParole =
-                    mInjector.currentTimeMillis() - mLastAppIdleParoledTime;
-            if (!deviceIdle
-                    && timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
-                if (DEBUG) {
-                    Slog.i(TAG,
-                            "Bringing idle apps out of inactive state due to deviceIdleMode=false");
-                }
-                paroled = true;
-            } else if (deviceIdle) {
-                if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
-                paroled = false;
-            } else {
-                return;
-            }
-        }
-        setAppIdleParoled(paroled);
-    }
-
     @Override
     public void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId) {
         if (!mAppIdleEnabled) return;
@@ -1038,11 +849,8 @@
     }
 
     @Override
-    public boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+    public boolean isAppIdleFiltered(String packageName, int userId, long elapsedRealtime,
             boolean shouldObfuscateInstantApps) {
-        if (isParoledOrCharging()) {
-            return false;
-        }
         if (shouldObfuscateInstantApps &&
                 mInjector.isPackageEphemeral(userId, packageName)) {
             return false;
@@ -1388,15 +1196,6 @@
         }
     }
 
-    private void informParoleStateChanged() {
-        final boolean paroled = isParoledOrCharging();
-        synchronized (mPackageAccessListeners) {
-            for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
-                listener.onParoleStateChanged(paroled);
-            }
-        }
-    }
-
     @Override
     public void flushToDisk(int userId) {
         synchronized (mAppIdleLock) {
@@ -1517,18 +1316,6 @@
         TimeUtils.formatDuration(mCheckIdleIntervalMillis, pw);
         pw.println();
 
-        pw.print("  mAppIdleParoleIntervalMillis=");
-        TimeUtils.formatDuration(mAppIdleParoleIntervalMillis, pw);
-        pw.println();
-
-        pw.print("  mAppIdleParoleWindowMillis=");
-        TimeUtils.formatDuration(mAppIdleParoleWindowMillis, pw);
-        pw.println();
-
-        pw.print("  mAppIdleParoleDurationMillis=");
-        TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
-        pw.println();
-
         pw.print("  mStrongUsageTimeoutMillis=");
         TimeUtils.formatDuration(mStrongUsageTimeoutMillis, pw);
         pw.println();
@@ -1566,22 +1353,11 @@
         TimeUtils.formatDuration(mSystemUpdateUsageTimeoutMillis, pw);
         pw.println();
 
-        pw.print("  mStableChargingThresholdMillis=");
-        TimeUtils.formatDuration(mStableChargingThresholdMillis, pw);
-        pw.println();
-
         pw.println();
         pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
-        pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
-        pw.print(" mCharging="); pw.print(mCharging);
-        pw.print(" mChargingStable="); pw.print(mChargingStable);
-        pw.print(" mLastAppIdleParoledTime=");
-        TimeUtils.formatDuration(now - mLastAppIdleParoledTime, pw);
         pw.println();
         pw.print("mScreenThresholds="); pw.println(Arrays.toString(mAppStandbyScreenThresholds));
         pw.print("mElapsedThresholds="); pw.println(Arrays.toString(mAppStandbyElapsedThresholds));
-        pw.print("mStableChargingThresholdMillis=");
-        TimeUtils.formatDuration(mStableChargingThresholdMillis, pw);
         pw.println();
     }
 
@@ -1655,10 +1431,6 @@
             return buildFlag && runtimeFlag;
         }
 
-        boolean isCharging() {
-            return mContext.getSystemService(BatteryManager.class).isCharging();
-        }
-
         boolean isPowerSaveWhitelistExceptIdleApp(String packageName) throws RemoteException {
             return mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName);
         }
@@ -1748,15 +1520,6 @@
                     checkIdleStates(UserHandle.USER_ALL);
                     break;
 
-                case MSG_CHECK_PAROLE_TIMEOUT:
-                    checkParoleTimeout();
-                    break;
-
-                case MSG_PAROLE_END_TIMEOUT:
-                    if (DEBUG) Slog.d(TAG, "Ending parole");
-                    setAppIdleParoled(false);
-                    break;
-
                 case MSG_REPORT_CONTENT_PROVIDER_USAGE:
                     SomeArgs args = (SomeArgs) msg.obj;
                     reportContentProviderUsage((String) args.arg1, // authority name
@@ -1765,11 +1528,6 @@
                     args.recycle();
                     break;
 
-                case MSG_PAROLE_STATE_CHANGED:
-                    if (DEBUG) Slog.d(TAG, "Parole state: " + mAppIdleTempParoled
-                            + ", Charging state:" + mChargingStable);
-                    informParoleStateChanged();
-                    break;
                 case MSG_CHECK_PACKAGE_IDLE_STATE:
                     checkAndUpdateStandbyState((String) msg.obj, msg.arg1, msg.arg2,
                             mInjector.elapsedRealtime());
@@ -1788,10 +1546,6 @@
                     reportExemptedSyncStart((String) msg.obj, msg.arg1);
                     break;
 
-                case MSG_UPDATE_STABLE_CHARGING:
-                    updateChargingStableState();
-                    break;
-
                 default:
                     super.handleMessage(msg);
                     break;
@@ -1800,23 +1554,6 @@
         }
     };
 
-    private class DeviceStateReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            switch (intent.getAction()) {
-                case BatteryManager.ACTION_CHARGING:
-                    setChargingState(true);
-                    break;
-                case BatteryManager.ACTION_DISCHARGING:
-                    setChargingState(false);
-                    break;
-                case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
-                    onDeviceIdleModeChanged();
-                    break;
-            }
-        }
-    }
-
     private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder().build();
 
     private final ConnectivityManager.NetworkCallback mNetworkCallback
@@ -1824,7 +1561,6 @@
         @Override
         public void onAvailable(Network network) {
             mConnectivityManager.unregisterNetworkCallback(this);
-            checkParoleTimeout();
         }
     };
 
@@ -1851,9 +1587,6 @@
      * Observe settings changes for {@link Global#APP_IDLE_CONSTANTS}.
      */
     private class SettingsObserver extends ContentObserver {
-        private static final String KEY_PAROLE_INTERVAL = "parole_interval";
-        private static final String KEY_PAROLE_WINDOW = "parole_window";
-        private static final String KEY_PAROLE_DURATION = "parole_duration";
         private static final String KEY_SCREEN_TIME_THRESHOLDS = "screen_thresholds";
         private static final String KEY_ELAPSED_TIME_THRESHOLDS = "elapsed_thresholds";
         private static final String KEY_STRONG_USAGE_HOLD_DURATION = "strong_usage_duration";
@@ -1875,7 +1608,6 @@
                 "system_interaction_duration";
         private static final String KEY_INITIAL_FOREGROUND_SERVICE_START_HOLD_DURATION =
                 "initial_foreground_service_start_duration";
-        private static final String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold";
         public static final long DEFAULT_STRONG_USAGE_TIMEOUT = 1 * ONE_HOUR;
         public static final long DEFAULT_NOTIFICATION_TIMEOUT = 12 * ONE_HOUR;
         public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR;
@@ -1885,7 +1617,6 @@
         public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT = 4 * ONE_HOUR;
         public static final long DEFAULT_EXEMPTED_SYNC_START_TIMEOUT = 10 * ONE_MINUTE;
         public static final long DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT = 10 * ONE_MINUTE;
-        public static final long DEFAULT_STABLE_CHARGING_THRESHOLD = 10 * ONE_MINUTE;
         public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT = 30 * ONE_MINUTE;
 
         private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -1932,17 +1663,6 @@
 
             synchronized (mAppIdleLock) {
 
-                // Default: 24 hours between paroles
-                mAppIdleParoleIntervalMillis = mParser.getDurationMillis(KEY_PAROLE_INTERVAL,
-                        COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE);
-
-                // Default: 2 hours to wait on network
-                mAppIdleParoleWindowMillis = mParser.getDurationMillis(KEY_PAROLE_WINDOW,
-                        COMPRESS_TIME ? ONE_MINUTE * 2 : 2 * 60 * ONE_MINUTE);
-
-                mAppIdleParoleDurationMillis = mParser.getDurationMillis(KEY_PAROLE_DURATION,
-                        COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes
-
                 String screenThresholdsValue = mParser.getString(KEY_SCREEN_TIME_THRESHOLDS, null);
                 mAppStandbyScreenThresholds = parseLongArray(screenThresholdsValue,
                         SCREEN_TIME_THRESHOLDS);
@@ -1997,10 +1717,6 @@
                         KEY_INITIAL_FOREGROUND_SERVICE_START_HOLD_DURATION,
                         COMPRESS_TIME ? ONE_MINUTE :
                                 DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT);
-
-                mStableChargingThresholdMillis = mParser.getDurationMillis(
-                        KEY_STABLE_CHARGING_THRESHOLD,
-                                COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STABLE_CHARGING_THRESHOLD);
             }
 
             // Check if app_idle_enabled has changed. Do this after getting the rest of the settings
diff --git a/apex/permission/Android.bp b/apex/permission/Android.bp
new file mode 100644
index 0000000..0274814
--- /dev/null
+++ b/apex/permission/Android.bp
@@ -0,0 +1,33 @@
+// 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.
+
+apex {
+    name: "com.android.permission",
+
+    manifest: "apex_manifest.json",
+
+    key: "com.android.permission.key",
+    certificate: ":com.android.permission.certificate",
+}
+
+apex_key {
+    name: "com.android.permission.key",
+    public_key: "com.android.permission.avbpubkey",
+    private_key: "com.android.permission.pem",
+}
+
+android_app_certificate {
+    name: "com.android.permission.certificate",
+    certificate: "com.android.permission",
+}
diff --git a/apex/permission/OWNERS b/apex/permission/OWNERS
new file mode 100644
index 0000000..957e10a
--- /dev/null
+++ b/apex/permission/OWNERS
@@ -0,0 +1,6 @@
+svetoslavganov@google.com
+moltmann@google.com
+eugenesusla@google.com
+zhanghai@google.com
+evanseverson@google.com
+ntmyren@google.com
diff --git a/apex/permission/apex_manifest.json b/apex/permission/apex_manifest.json
new file mode 100644
index 0000000..2a8c4f7
--- /dev/null
+++ b/apex/permission/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.permission",
+  "version": 1
+}
diff --git a/apex/permission/com.android.permission.avbpubkey b/apex/permission/com.android.permission.avbpubkey
new file mode 100644
index 0000000..9eaf852
--- /dev/null
+++ b/apex/permission/com.android.permission.avbpubkey
Binary files differ
diff --git a/apex/permission/com.android.permission.pem b/apex/permission/com.android.permission.pem
new file mode 100644
index 0000000..3d584be
--- /dev/null
+++ b/apex/permission/com.android.permission.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEA6snt4eqoz85xiL9Sf6w1S1b9FgSHK05zYTh2JYPvQKQ3yeZp
+E6avJ6FN6XcbmkDzSd658BvUGDBSPhOlzuUO4BsoKBuLMxP6TxIQXFKidzDqY0vQ
+4qkS++bdIhUjwBP3OSZ3Czu0BiihK8GC75Abr//EyCyObGIGGfHEGANiOgrpP4X5
++OmLzQLCjk4iE1kg+U6cRSRI/XLaoWC0TvIIuzxznrQ6r5GmzgTOwyBWyIB+bj73
+bmsweHTU+w9Y7kGOx4hO3XCLIhoBWEw0EbuW9nZmQ4sZls5Jo/CbyJlCclF11yVo
+SCf2LG/T+9pah5NOmDQ1kPbU+0iKZIV4YFHGTIhyGDE/aPOuUT05ziCGDifgHr0u
+SG1x/RLqsVh/POvNxnvP9cQFMQ08BvbEJaTTgB785iwKsvdqCfmng/SAyxSetmzP
+StXVB3fh1OoZ8vunRbQYxnmUxycVqaA96zmBx2wLvbvzKo7pZFDE6nbhnT5+MRAM
+z/VIK89W26uB4gj8sBFslqZjT0jPqsAZuvDm7swOtMwIcEolyGJuFLqlhN7UwMz2
+9y8+IpYixR+HvD1TZI9NtmuCmv3kPrWgoMZg6yvaBayTIr8RdYzi6FO/C1lLiraz
+48dH3sXWRa8cgw6VcSUwYrEBIc3sotdsupO1iOjcFybIwaee0YTZJfjvbqkCAwEA
+AQKCAgEArRnfdpaJi1xLPGTCMDsIt9kUku0XswgN7PmxsYsKFAB+2S40/jYAIRm9
+1YjpItsMA8RgFfSOdJ77o6TctCMQyo17F8bm4+uwuic5RLfv7Cx2QmsdQF8jDfFx
+y7UGPJD7znjbf76uxXOjEB2FqZX3s9TAgkzHXIUQtoQW7RVhkCWHPjxKxgd5+NY2
+FrDoUpd9xhD9CcTsw1+wbRZdGW88nL6/B50dP2AFORM2VYo8MWr6y9FEn3YLsGOC
+uu7fxBk1aUrHyl81VRkTMMROB1zkuiUk1FtzrEm+5U15rXXBFYOVe9+qeLhtuOlh
+wueDoz0pzvF/JLe24uTik6YL0Ae6SD0pFXQ2KDrdH3cUHLok3r76/yGzaDNTFjS2
+2WbQ8dEJV8veNHk8gjGpFTJIsBUlcZpmUCDHlfvVMb3+2ahQ+28piQUt5t3zqJdZ
+NDqsOHzY6BRPc+Wm85Xii/lWiQceZSee/b1Enu+nchsyXhSenBfC6bIGZReyMI0K
+KKKuVhyR6OSOiR5ZdZ/NyXGqsWy05fn/h0X9hnpETsNaNYNKWvpHLfKll+STJpf7
+AZquJPIclQyiq5NONx6kfPztoCLkKV/zOgIj3Sx5oSZq+5gpO91nXWVwkTbqK1d1
+004q2Mah6UQyAk1XGQc2pHx7ouVcWawjU30vZ4C015Hv2lm/gVkCggEBAPltATYS
+OqOSL1YAtIHPiHxMjNAgUdglq8JiJFXVfkocGU9eNub3Ed3sSWu6GB9Myu/sSKje
+bJ5DZqxJnvB2Fqmu9I9OunLGFSD0aXs4prwsQ1Rm5FcbImtrxcciASdkoo8Pj0z4
+vk2r2NZD3VtER5Uh+YjSDkxcS9gBStXUpCL6gj69UpOxMmWqZVjyHatVB4lEvYJl
+N82uT7N7QVNL1DzcZ9z4C4r7ks1Pm7ka12s5m/oaAlAMdVeofiPJe1xA9zRToSr4
+tIbMkOeXFLVRLuji/7XsOgal5Rl59p+OwLshX5cswPVOMrH6zt+hbsJ5q8M5dqnX
+VAOBK7KNQ/EKZwcCggEBAPD6KVvyCim46n5EbcEqCkO7gevwZkw/9vLwmM5YsxTh
+z9FQkPO0iB7mwbX8w04I91Pre4NdfcgMG0pP1b13Sb4KHBchqW1a+TCs3kSGC6gn
+1SxmXHnA9jRxAkrWlGkoAQEz+aP61cXiiy2tXpQwJ8xQCKprfoqWZwhkCtEVU6CE
+S7v9cscOHIqgNxx4WoceMmq4EoihHAZzHxTcNVbByckMjb2XQJ0iNw3lDP4ddvc+
+a4HzHfHkhzeQ5ZNc8SvWU8z80aSCOKRsSD3aUTZzxhZ4O2tZSW7v7p+FpvVee7bC
+g8YCfszTdpVUMlLRLjScimAcovcFLSvtyupinxWg4M8CggEAN9YGEmOsSte7zwXj
+YrfhtumwEBtcFwX/2Ej+F1Tuq4p0xAa0RaoDjumJWhtTsRYQy/raHSuFpzwxbNoi
+QXQ+CIhI6RfXtz/OlQ0B2/rHoJJMFEXgUfuaDfAXW0eqeHYXyezSyIlamKqipPyW
+Pgsf9yue39keKEv1EorfhNTQVaA8rezV4oglXwrxGyNALw2e3UTNI7ai8mFWKDis
+XAg6n9E7UwUYGGnO6DUtCBgRJ0jDOQ6/e8n+LrxiWIKPIgzNCiK6jpMUXqTGv4Fb
+umdNGAdQ9RnHt5tFmRlrczaSwJFtA7uaCpAR2zPpQbiywchZAiAIB2dTwGEXNiZX
+kksg2wKCAQEA6pNad3qhkgPDoK6T+Jkn7M82paoaqtcJWWwEE7oceZNnbWZz9Agl
+CY+vuawXonrv5+0vCq2Tp4zBdBFLC2h3jFrjBVFrUFxifpOIukOSTVqZFON/2bWQ
+9XOcu6UuSz7522Xw+UNPnZXtzcUacD6AP08ZYGvLfrTyDyTzspyED5k48ALEHCkM
+d5WGkFxII4etpF0TDZVnZo/iDbhe49k4yFFEGO6Ho26PESOLBkNAb2V/2bwDxlij
+l9+g21Z6HiZA5SamHPH2mXgeyrcen1cL2QupK9J6vVcqfnboE6qp2zp2c+Yx8MlY
+gfy4EA44YFaSDQVTTgrn8f9Eq+zc130H2QKCAQEAqOKgv68nIPdDSngNyCVyWego
+boFiDaEJoBBg8FrBjTJ6wFLrNAnXmbvfTtgNmNAzF1cUPJZlIIsHgGrMCfpehbXq
+WQQIw+E+yFbTGLxseGRfsLrV0CsgnAoOVeod+yIHmqc3livaUbrWhL1V2f6Ue+sE
+7YLp/iP43NaMfA4kYk2ep7+ZJoEVkCjHJJaHWgAG3RynPJHkTJlSgu7wLYvGc9uE
+ZsEFUM46lX02t7rrtMfasVGrUy1c2xOxFb4v1vG6iEZ7+YWeq5o3AkxUwEGn+mG4
+/3p+k4AaTXJDXgyZ0Sv6CkGuPHenAYG4cswcUUEf/G4Ag77x6LBNMgycJBxUJA==
+-----END RSA PRIVATE KEY-----
diff --git a/apex/permission/com.android.permission.pk8 b/apex/permission/com.android.permission.pk8
new file mode 100644
index 0000000..d51673d
--- /dev/null
+++ b/apex/permission/com.android.permission.pk8
Binary files differ
diff --git a/apex/permission/com.android.permission.x509.pem b/apex/permission/com.android.permission.x509.pem
new file mode 100644
index 0000000..4b146c9
--- /dev/null
+++ b/apex/permission/com.android.permission.x509.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGKzCCBBOgAwIBAgIUezo3fQeVZsmLpm/dkpGWJ/G/MN8wDQYJKoZIhvcNAQEL
+BQAwgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMR8wHQYDVQQDDBZjb20uYW5kcm9pZC5wZXJtaXNzaW9uMSIwIAYJKoZIhvcN
+AQkBFhNhbmRyb2lkQGFuZHJvaWQuY29tMCAXDTE5MTAwOTIxMzExOVoYDzQ3NTcw
+OTA0MjEzMTE5WjCBozELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx
+FjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNV
+BAsMB0FuZHJvaWQxHzAdBgNVBAMMFmNvbS5hbmRyb2lkLnBlcm1pc3Npb24xIjAg
+BgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCxefguRJ7E6tBCTEOeU2HJEGs6AQQapLz9hMed0aaJ
+Qr7aTQiYJEk+sG4+jPYbjpxa8JDDzJHp+4g7DjfSb+dvT9n84A8lWaI/yRXTZTQN
+Hu5m/bgHhi0LbySpiaFyodXBKUAnOhZyGPtYjtBFywFylueub8ryc1Z6UxxU7udH
+1mkIr7sE48Qkq5SyjFROE96iFmYA+vS/JXOfS0NBHiMB4GBxx4V7kXpvrTI7hhZG
+HiyhKvNh7wyHIhO9nDEw1rwtAH6CsL3YkQEVBeAU98m+0Au+qStLYkKHh2l8zT4W
+7sVK1VSqfB+VqOUmeIGdzlBfqMsoXD+FJz6KnIdUHIwjFDjL7Xr+hd+7xve+Q3S+
+U3Blk/U6atY8PM09wNfilG+SvwcKk5IgriDcu3rWKgIFxbUUaxLrDW7pLlu6wt/d
+GGtKK+Bc0jF+9Z901Tl33i5xhc5yOktT0btkKs7lSeE6VzP/Nk5g0SuzixmuRoh9
+f5Ge41N2ZCEHNXx3wZeVZwHIIPfYrL7Yql1Xoxbfs4ETFk6ChzVQcvjfDQQuK58J
+uNc+TOCoI/qflXwGCwpuHl0ier8V5Z4tpMUl5rWyVR/QGRtLPvs2lLuxczDw1OXq
+wEVtCMn9aNnd4y7R9PZ52hi53HAvDjpWefrLYi+Q04J6iGFQ1qAFBClK9DquBvmR
+swIDAQABo1MwUTAdBgNVHQ4EFgQULpfus5s5SrqLkoUKyPXA0D1iHPMwHwYDVR0j
+BBgwFoAULpfus5s5SrqLkoUKyPXA0D1iHPMwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAgEAjxQG5EFv8V/9yV2glI53VOmlWMjfEgvUjd39s/XLyPlr
+OzPOKSB0NFo8To3l4l+MsManxPK8y0OyfEVKbWVz9onv0ovo5MVokBmV/2G0jmsV
+B4e9yjOq+DmqIvY/Qh63Ywb97sTgcFI8620MhQDbh2IpEGv4ZNV0H6rgXmgdSCBw
+1EjBoYfFpN5aMgZjeyzZcq+d1IapdWqdhuEJQkMvoYS4WIumNIJlEXPQRoq/F5Ih
+nszdbKI/jVyiGFa2oeZ3rja1Y6GCRU8TYEoKx1pjS8uQDOEDTwsG/QnUe9peEj0V
+SsCkIidJWTomAmq9Tub9vpBe1zuTpuRAwxwR0qwgSxozV1Mvow1dJ19oFtHX0yD6
+ZjCpRn5PW9kMvSWSlrcrFs1NJf0j1Cvf7bHpkEDqLqpMnnh9jaFQq3nzDY+MWcIR
+jDcgQpI+AiE2/qtauZnFEVhbce49nCnk9+5bpTTIZJdzqeaExe5KXHwEtZLaEDh4
+atLY9LuEvPsjmDIMOR6hycD9FvwGXhJOQBjESIWFwigtSb1Yud9n6201jw3MLJ4k
++WhkbmZgWy+xc+Mdm5H3XyB1lvHaHGkxu+QB9KyQuVQKwbUVcbwZIfTFPN6Zr/dS
+ZXJqAbBhG/dBgF0LazuLaPVpibi+a3Y+tb9b8eXGkz4F97PWZIEDkELQ+9KOvhc=
+-----END CERTIFICATE-----
diff --git a/apex/statsd/.clang-format b/apex/statsd/.clang-format
new file mode 100644
index 0000000..cead3a0
--- /dev/null
+++ b/apex/statsd/.clang-format
@@ -0,0 +1,17 @@
+BasedOnStyle: Google
+AllowShortIfStatementsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: false
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+AccessModifierOffset: -4
+IncludeCategories:
+  - Regex:    '^"Log\.h"'
+    Priority:    -1
diff --git a/api/current.txt b/api/current.txt
index b176675..6d2221e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2946,6 +2946,7 @@
     field public static final int FEEDBACK_SPOKEN = 1; // 0x1
     field public static final int FEEDBACK_VISUAL = 8; // 0x8
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
+    field public static final int FLAG_HANDLE_SHORTCUT = 2048; // 0x800
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
     field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
@@ -3881,6 +3882,7 @@
     method public void setTitle(CharSequence);
     method public void setTitle(int);
     method @Deprecated public void setTitleColor(int);
+    method public boolean setTranslucent(boolean);
     method public void setTurnScreenOn(boolean);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
@@ -4278,23 +4280,24 @@
     method @Deprecated public int checkOp(@NonNull String, int, @NonNull String);
     method @Deprecated public int checkOpNoThrow(@NonNull String, int, @NonNull String);
     method public void checkPackage(int, @NonNull String);
-    method public void finishOp(@NonNull String, int, @NonNull String);
+    method @Deprecated public void finishOp(@NonNull String, int, @NonNull String);
+    method public void finishOp(@NonNull String, int, @NonNull String, @Nullable String);
     method public boolean isOpActive(@NonNull String, int, @NonNull String);
     method @Deprecated public int noteOp(@NonNull String, int, @NonNull String);
-    method public int noteOp(@NonNull String, int, @Nullable String, @Nullable String);
+    method public int noteOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
     method @Deprecated public int noteOpNoThrow(@NonNull String, int, @NonNull String);
-    method public int noteOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String);
+    method public int noteOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String, @Nullable String);
     method @Deprecated public int noteProxyOp(@NonNull String, @NonNull String);
-    method public int noteProxyOp(@NonNull String, @Nullable String, int, @Nullable String);
+    method public int noteProxyOp(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
     method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @NonNull String);
     method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
-    method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String);
+    method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
     method public static String permissionToOp(String);
     method public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
     method @Deprecated public int startOp(@NonNull String, int, @NonNull String);
-    method public int startOp(@NonNull String, int, @Nullable String, @Nullable String);
+    method public int startOp(@NonNull String, int, @Nullable String, @NonNull String, @Nullable String);
     method @Deprecated public int startOpNoThrow(@NonNull String, int, @NonNull String);
-    method public int startOpNoThrow(@NonNull String, int, @NonNull String, @Nullable String);
+    method public int startOpNoThrow(@NonNull String, int, @NonNull String, @NonNull String, @Nullable String);
     method public void startWatchingActive(@NonNull String[], @NonNull java.util.concurrent.Executor, @NonNull android.app.AppOpsManager.OnOpActiveChangedListener);
     method public void startWatchingMode(@NonNull String, @Nullable String, @NonNull android.app.AppOpsManager.OnOpChangedListener);
     method public void startWatchingMode(@NonNull String, @Nullable String, int, @NonNull android.app.AppOpsManager.OnOpChangedListener);
@@ -4476,12 +4479,13 @@
 
   public final class AsyncNotedAppOp implements android.os.Parcelable {
     method public int describeContents();
+    method @Nullable public String getFeatureId();
     method @NonNull public String getMessage();
     method @Nullable public String getNotingPackageName();
     method @IntRange(from=0) public int getNotingUid();
     method @NonNull public String getOp();
     method @IntRange(from=0) public long getTime();
-    method public void writeToParcel(android.os.Parcel, int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AsyncNotedAppOp> CREATOR;
   }
 
@@ -6300,6 +6304,7 @@
   }
 
   public final class SyncNotedAppOp {
+    method @Nullable public String getFeatureId();
     method @NonNull public String getOp();
   }
 
@@ -6846,6 +6851,7 @@
     method public boolean setKeyPairCertificate(@Nullable android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.security.cert.Certificate>, boolean);
     method public boolean setKeyguardDisabled(@NonNull android.content.ComponentName, boolean);
     method public void setKeyguardDisabledFeatures(@NonNull android.content.ComponentName, int);
+    method public void setLocationEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setLockTaskFeatures(@NonNull android.content.ComponentName, int);
     method public void setLockTaskPackages(@NonNull android.content.ComponentName, @NonNull String[]) throws java.lang.SecurityException;
     method public void setLogoutEnabled(@NonNull android.content.ComponentName, boolean);
@@ -9484,6 +9490,7 @@
     method @Nullable public android.database.Cursor query(@NonNull android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal);
     method @Nullable public android.database.Cursor query(@NonNull android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal);
     method public boolean refresh(android.net.Uri, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal);
+    method @NonNull public final android.content.Context requireContext();
     method public final void restoreCallingIdentity(@NonNull android.content.ContentProvider.CallingIdentity);
     method protected final void setPathPermissions(@Nullable android.content.pm.PathPermission[]);
     method protected final void setReadPermission(@Nullable String);
@@ -9776,6 +9783,7 @@
     method public abstract android.content.Context createContextForSplit(String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display);
+    method @NonNull public android.content.Context createFeatureContext(@Nullable String);
     method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract String[] databaseList();
     method public abstract boolean deleteDatabase(String);
@@ -9807,6 +9815,7 @@
     method @Nullable public abstract java.io.File getExternalFilesDir(@Nullable String);
     method public abstract java.io.File[] getExternalFilesDirs(String);
     method @Deprecated public abstract java.io.File[] getExternalMediaDirs();
+    method @Nullable public String getFeatureId();
     method public abstract java.io.File getFileStreamPath(String);
     method public abstract java.io.File getFilesDir();
     method public java.util.concurrent.Executor getMainExecutor();
@@ -13772,7 +13781,9 @@
   public enum Bitmap.CompressFormat {
     enum_constant public static final android.graphics.Bitmap.CompressFormat JPEG;
     enum_constant public static final android.graphics.Bitmap.CompressFormat PNG;
-    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP;
+    enum_constant @Deprecated public static final android.graphics.Bitmap.CompressFormat WEBP;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP_LOSSLESS;
+    enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP_LOSSY;
   }
 
   public enum Bitmap.Config {
@@ -23139,6 +23150,7 @@
     method @Deprecated public void clearTestProviderStatus(@NonNull String);
     method @NonNull public java.util.List<java.lang.String> getAllProviders();
     method @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getGnssHardwareModelName();
     method public int getGnssYearOfHardware();
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
@@ -25419,22 +25431,22 @@
   public class MediaMetadataRetriever implements java.lang.AutoCloseable {
     ctor public MediaMetadataRetriever();
     method public void close();
-    method public String extractMetadata(int);
-    method public byte[] getEmbeddedPicture();
-    method public android.graphics.Bitmap getFrameAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getFrameAtIndex(int);
-    method public android.graphics.Bitmap getFrameAtTime(long, int);
-    method public android.graphics.Bitmap getFrameAtTime(long, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getFrameAtTime(long);
-    method public android.graphics.Bitmap getFrameAtTime();
+    method @Nullable public String extractMetadata(int);
+    method @Nullable public byte[] getEmbeddedPicture();
+    method @Nullable public android.graphics.Bitmap getFrameAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getFrameAtIndex(int);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime(long, int);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime(long, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime(long);
+    method @Nullable public android.graphics.Bitmap getFrameAtTime();
     method @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
     method @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int);
-    method public android.graphics.Bitmap getImageAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getImageAtIndex(int);
-    method public android.graphics.Bitmap getPrimaryImage(@NonNull android.media.MediaMetadataRetriever.BitmapParams);
-    method public android.graphics.Bitmap getPrimaryImage();
-    method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
-    method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getImageAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getImageAtIndex(int);
+    method @Nullable public android.graphics.Bitmap getPrimaryImage(@NonNull android.media.MediaMetadataRetriever.BitmapParams);
+    method @Nullable public android.graphics.Bitmap getPrimaryImage();
+    method @Nullable public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
+    method @Nullable public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
     method public void release();
     method public void setDataSource(String) throws java.lang.IllegalArgumentException;
     method public void setDataSource(String, java.util.Map<java.lang.String,java.lang.String>) throws java.lang.IllegalArgumentException;
@@ -28922,7 +28934,9 @@
     method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]);
     method @NonNull public static android.net.MacAddress fromString(@NonNull String);
     method public int getAddressType();
+    method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac();
     method public boolean isLocallyAssigned();
+    method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
     method @NonNull public byte[] toByteArray();
     method @NonNull public String toOuiString();
     method public void writeToParcel(android.os.Parcel, int);
@@ -29963,16 +29977,23 @@
     method public String getSSID();
     method public android.net.wifi.SupplicantState getSupplicantState();
     method @IntRange(from=0xffffffff) public int getTxLinkSpeedMbps();
+    method public int getWifiTechnology();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final String FREQUENCY_UNITS = "MHz";
     field public static final String LINK_SPEED_UNITS = "Mbps";
     field public static final int LINK_SPEED_UNKNOWN = -1; // 0xffffffff
+    field public static final int WIFI_TECHNOLOGY_11AC = 5; // 0x5
+    field public static final int WIFI_TECHNOLOGY_11AX = 6; // 0x6
+    field public static final int WIFI_TECHNOLOGY_11N = 4; // 0x4
+    field public static final int WIFI_TECHNOLOGY_LEGACY = 1; // 0x1
+    field public static final int WIFI_TECHNOLOGY_UNKNOWN = 0; // 0x0
   }
 
   public class WifiManager {
     method @Deprecated public int addNetwork(android.net.wifi.WifiConfiguration);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void addScanResultsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.ScanResultsListener);
     method public static int calculateSignalLevel(int, int);
     method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
@@ -30008,6 +30029,7 @@
     method @Deprecated public boolean removeNetwork(int);
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_CARRIER_PROVISIONING"}) public void removePasspointConfiguration(String);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeScanResultsListener(@NonNull android.net.wifi.WifiManager.ScanResultsListener);
     method @Deprecated public boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(String, boolean);
@@ -30083,6 +30105,10 @@
     method public void setReferenceCounted(boolean);
   }
 
+  public static interface WifiManager.ScanResultsListener {
+    method public void onScanResultsAvailable();
+  }
+
   public class WifiManager.WifiLock {
     method public void acquire();
     method public boolean isHeld();
@@ -30134,6 +30160,7 @@
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsHiddenSsid(boolean);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsMetered(boolean);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
@@ -30317,6 +30344,8 @@
     method public int describeContents();
     method public android.net.wifi.hotspot2.pps.Credential getCredential();
     method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
+    method public long getSubscriptionExpirationTimeInMillis();
+    method public boolean isOsuProvisioned();
     method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
     method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
     method public void writeToParcel(android.os.Parcel, int);
@@ -37071,6 +37100,7 @@
     field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
     field public static final int FEATURES_RTT = 32; // 0x20
     field public static final int FEATURES_VIDEO = 1; // 0x1
+    field public static final int FEATURES_VOLTE = 64; // 0x40
     field public static final int FEATURES_WIFI = 8; // 0x8
     field public static final String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -41348,11 +41378,16 @@
     field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
     field public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1; // 0x1
+    field public static final int POSITIVE_BUTTON_STYLE_CONTINUE = 1; // 0x1
+    field public static final int POSITIVE_BUTTON_STYLE_SAVE = 0; // 0x0
     field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
     field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
+    field public static final int SAVE_DATA_TYPE_DEBIT_CARD = 32; // 0x20
     field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
     field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+    field public static final int SAVE_DATA_TYPE_GENERIC_CARD = 128; // 0x80
     field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
+    field public static final int SAVE_DATA_TYPE_PAYMENT_CARD = 64; // 0x40
     field public static final int SAVE_DATA_TYPE_USERNAME = 8; // 0x8
   }
 
@@ -41366,6 +41401,7 @@
     method @NonNull public android.service.autofill.SaveInfo.Builder setFlags(int);
     method @NonNull public android.service.autofill.SaveInfo.Builder setNegativeAction(int, @Nullable android.content.IntentSender);
     method @NonNull public android.service.autofill.SaveInfo.Builder setOptionalIds(@NonNull android.view.autofill.AutofillId[]);
+    method @NonNull public android.service.autofill.SaveInfo.Builder setPositiveAction(int);
     method @NonNull public android.service.autofill.SaveInfo.Builder setTriggerId(@NonNull android.view.autofill.AutofillId);
     method @NonNull public android.service.autofill.SaveInfo.Builder setValidator(@NonNull android.service.autofill.Validator);
   }
@@ -43466,8 +43502,10 @@
     method public final int getState();
     method public final android.telecom.StatusHints getStatusHints();
     method public final android.telecom.Connection.VideoProvider getVideoProvider();
+    method public final int getVideoState();
     method public void handleRttUpgradeResponse(@Nullable android.telecom.Connection.RttTextStream);
     method public final boolean isRingbackRequested();
+    method public final void notifyConferenceMergeFailed();
     method public void onAbort();
     method public void onAnswer(int);
     method public void onAnswer();
@@ -43546,8 +43584,15 @@
     field public static final int CAPABILITY_SUPPORT_DEFLECT = 33554432; // 0x2000000
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED";
     field public static final String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
     field public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+    field public static final String EVENT_CALL_REMOTELY_HELD = "android.telecom.event.CALL_REMOTELY_HELD";
+    field public static final String EVENT_CALL_REMOTELY_UNHELD = "android.telecom.event.CALL_REMOTELY_UNHELD";
+    field public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE";
+    field public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START";
+    field public static final String EVENT_ON_HOLD_TONE_END = "android.telecom.event.ON_HOLD_TONE_END";
+    field public static final String EVENT_ON_HOLD_TONE_START = "android.telecom.event.ON_HOLD_TONE_START";
     field public static final String EVENT_RTT_AUDIO_INDICATION_CHANGED = "android.telecom.event.RTT_AUDIO_INDICATION_CHANGED";
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
     field public static final String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
@@ -43557,9 +43602,12 @@
     field public static final String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
     field public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE";
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
+    field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
     field public static final int PROPERTY_IS_RTT = 256; // 0x100
+    field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400
     field public static final int PROPERTY_SELF_MANAGED = 128; // 0x80
+    field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_DIALING = 3; // 0x3
     field public static final int STATE_DISCONNECTED = 6; // 0x6
@@ -44256,6 +44304,7 @@
     field public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
     field public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
     field public static final String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
+    field public static final String KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING = "default_vm_number_roaming_and_ims_unregistered_string";
     field public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
     field public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
     field public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
@@ -44461,6 +44510,8 @@
   public abstract class CellInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getCellConnectionStatus();
+    method @NonNull public abstract android.telephony.CellIdentity getCellIdentity();
+    method @NonNull public abstract android.telephony.CellSignalStrength getCellSignalStrength();
     method public long getTimeStamp();
     method public boolean isRegistered();
     field public static final int CONNECTION_NONE = 0; // 0x0
@@ -45153,7 +45204,7 @@
     method public int getDataState();
     method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId();
     method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion();
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public String getDeviceSoftwareVersion();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String[] getForbiddenPlmns();
@@ -50228,14 +50279,14 @@
   }
 
   public static interface SurfaceHolder.Callback {
-    method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
-    method public void surfaceCreated(android.view.SurfaceHolder);
-    method public void surfaceDestroyed(android.view.SurfaceHolder);
+    method public void surfaceChanged(@NonNull android.view.SurfaceHolder, int, @IntRange(from=0) int, @IntRange(from=0) int);
+    method public void surfaceCreated(@NonNull android.view.SurfaceHolder);
+    method public void surfaceDestroyed(@NonNull android.view.SurfaceHolder);
   }
 
   public static interface SurfaceHolder.Callback2 extends android.view.SurfaceHolder.Callback {
-    method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
-    method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, Runnable);
+    method public void surfaceRedrawNeeded(@NonNull android.view.SurfaceHolder);
+    method public default void surfaceRedrawNeededAsync(@NonNull android.view.SurfaceHolder, @NonNull Runnable);
   }
 
   public class SurfaceView extends android.view.View {
diff --git a/api/system-current.txt b/api/system-current.txt
index 6e35200..79650fc 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -458,6 +458,7 @@
   public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
     method public int describeContents();
     method public long getDuration();
+    method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
     method public long getLastAccessBackgroundTime(int);
     method public long getLastAccessForegroundTime(int);
     method public long getLastAccessTime(int);
@@ -471,13 +472,35 @@
     method public long getLastRejectTime(int, int, int);
     method public int getMode();
     method @NonNull public String getOpStr();
+    method @Deprecated @Nullable public String getProxyPackageName();
+    method @Nullable public String getProxyPackageName(int, int);
+    method @Deprecated public int getProxyUid();
+    method public int getProxyUid(int, int);
+    method public boolean isRunning();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
+  }
+
+  public static final class AppOpsManager.OpFeatureEntry {
+    method public long getDuration();
+    method public long getLastAccessBackgroundTime(int);
+    method public long getLastAccessForegroundTime(int);
+    method public long getLastAccessTime(int);
+    method public long getLastAccessTime(int, int, int);
+    method public long getLastBackgroundDuration(int);
+    method public long getLastDuration(int, int, int);
+    method public long getLastForegroundDuration(int);
+    method public long getLastRejectBackgroundTime(int);
+    method public long getLastRejectForegroundTime(int);
+    method public long getLastRejectTime(int);
+    method public long getLastRejectTime(int, int, int);
+    method @Nullable public String getProxyFeatureId();
+    method @Nullable public String getProxyFeatureId(int, int);
     method @Nullable public String getProxyPackageName();
     method @Nullable public String getProxyPackageName(int, int);
     method public int getProxyUid();
     method public int getProxyUid(int, int);
     method public boolean isRunning();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
   }
 
   public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
@@ -1406,6 +1429,7 @@
     field public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
     field public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
     field public static final String ACTION_DEVICE_CUSTOMIZATION_READY = "android.intent.action.DEVICE_CUSTOMIZATION_READY";
+    field public static final String ACTION_DIAL_EMERGENCY = "android.intent.action.DIAL_EMERGENCY";
     field public static final String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";
     field public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
     field public static final String ACTION_INCIDENT_REPORT_READY = "android.intent.action.INCIDENT_REPORT_READY";
@@ -3430,6 +3454,7 @@
 
   public class LocationManager {
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getExtraLocationControllerPackage();
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize();
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GnssCapabilities getGnssCapabilities();
@@ -3625,6 +3650,10 @@
     method public void stop();
   }
 
+  public class RingtoneManager {
+    method @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public static void ensureDefaultRingtones(@NonNull android.content.Context);
+  }
+
 }
 
 package android.media.audiopolicy {
@@ -4708,6 +4737,7 @@
     method @Deprecated public boolean hasNoInternetAccess();
     method @Deprecated public boolean isEphemeral();
     method @Deprecated public boolean isNoInternetAccessExpected();
+    field @Deprecated public boolean allowAutojoin;
     field @Deprecated public String creatorName;
     field @Deprecated public int creatorUid;
     field @Deprecated public String lastUpdateName;
@@ -4730,6 +4760,7 @@
 
   public class WifiManager {
     method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void addOnWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
+    method @RequiresPermission("android.permission.NETWORK_SETTINGS") public void allowAutojoin(int, boolean);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener);
     method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener);
@@ -4751,8 +4782,11 @@
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource);
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_STACK", android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startSoftAp(@Nullable android.net.wifi.WifiConfiguration);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession();
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_STACK", android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp();
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_STACK", android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateInterfaceIpState(@Nullable String, int);
     method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void updateWifiUsabilityScore(int, int, int);
     field public static final int CHANGE_REASON_ADDED = 0; // 0x0
     field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2
@@ -4767,10 +4801,16 @@
     field public static final String EXTRA_CHANGE_REASON = "changeReason";
     field public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
     field public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
+    field public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME";
+    field public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE";
     field public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
     field public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
     field public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
     field public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
+    field public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; // 0x0
+    field public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; // 0x2
+    field public static final int IFACE_IP_MODE_TETHERED = 1; // 0x1
+    field public static final int IFACE_IP_MODE_UNSPECIFIED = -1; // 0xffffffff
     field public static final int PASSPOINT_HOME_NETWORK = 0; // 0x0
     field public static final int PASSPOINT_ROAMING_NETWORK = 1; // 0x1
     field public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
@@ -4807,6 +4847,7 @@
   public class WifiScanner {
     method @Deprecated public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.BssidInfo[]);
     method @Deprecated public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
+    method @Nullable @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<java.lang.Integer> getAvailableChannels(int);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean getScanResults();
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener, android.os.WorkSource);
@@ -5210,6 +5251,7 @@
     field public static final String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS";
     field public static final String ACTION_UPDATE_CONVERSATION_ACTIONS = "android.intent.action.UPDATE_CONVERSATION_ACTIONS";
     field public static final String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS";
+    field public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB = "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
     field public static final String ACTION_UPDATE_INTENT_FIREWALL = "android.intent.action.UPDATE_INTENT_FIREWALL";
     field public static final String ACTION_UPDATE_LANG_ID = "android.intent.action.UPDATE_LANG_ID";
     field public static final String ACTION_UPDATE_NETWORK_WATCHLIST = "android.intent.action.UPDATE_NETWORK_WATCHLIST";
@@ -5606,6 +5648,8 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isPrimaryUser();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean isUserUnlockingOrUnlocked(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
@@ -5691,14 +5735,6 @@
 
 }
 
-package android.os.telephony {
-
-  public class TelephonyRegistryManager {
-    method public void notifyCarrierNetworkChange(boolean);
-  }
-
-}
-
 package android.permission {
 
   public final class PermissionControllerManager {
@@ -5908,6 +5944,7 @@
     field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
     field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
     field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service";
+    field public static final String NAMESPACE_PERMISSIONS = "permissions";
     field public static final String NAMESPACE_PRIVACY = "privacy";
     field public static final String NAMESPACE_ROLLBACK = "rollback";
     field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
@@ -7007,7 +7044,26 @@
 
   public abstract class Connection extends android.telecom.Conferenceable {
     method @Deprecated public final android.telecom.AudioState getAudioState();
+    method public final int getCallRadioTech();
+    method public final long getConnectElapsedTimeMillis();
+    method public final long getConnectTimeMillis();
+    method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
+    method @Nullable public final String getTelecomCallId();
     method @Deprecated public void onAudioStateChanged(android.telecom.AudioState);
+    method public final void resetConnectionTime();
+    method public void setCallDirection(int);
+    method public final void setCallRadioTech(int);
+    method public final void setConnectTimeMillis(long);
+    method public final void setConnectionStartElapsedRealTime(long);
+    method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
+    method public void setTelecomCallId(@NonNull String);
+    field public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 2097152; // 0x200000
+    field public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 262144; // 0x40000
+    field public static final String EXTRA_DISABLE_ADD_CALL = "android.telecom.extra.DISABLE_ADD_CALL";
+    field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1; // 0x1
+    field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
+    field public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 64; // 0x40
+    field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800
   }
 
   public abstract class InCallService extends android.app.Service {
@@ -7203,6 +7259,7 @@
     method public void addNewUnknownCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method @Deprecated public void clearAccounts();
     method public void clearPhoneAccounts();
+    method @NonNull public android.content.Intent createLaunchEmergencyDialerIntent(@Nullable String);
     method @RequiresPermission(android.Manifest.permission.DUMP) public android.telecom.TelecomAnalytics dumpAnalytics();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean);
     method public java.util.List<android.telecom.PhoneAccountHandle> getAllPhoneAccountHandles();
@@ -8243,6 +8300,9 @@
 
   public class TelephonyManager {
     method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void carrierActionReportDefaultNetworkStatus(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void carrierActionResetAll(int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void carrierActionSetRadioEnabled(int, boolean);
     method public int checkCarrierPrivilegesForPackage(String);
     method public int checkCarrierPrivilegesForPackageAnyPhone(String);
     method public void dial(String);
@@ -8265,6 +8325,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getDataActivationState();
     method @Deprecated public boolean getDataEnabled();
     method @Deprecated public boolean getDataEnabled(int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
@@ -8379,6 +8440,14 @@
     field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
   }
 
+  public class TelephonyRegistryManager {
+    method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
+    method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
+    method public void notifyCarrierNetworkChange(boolean);
+    method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
+    method public void removeOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+  }
+
   public final class UiccAccessRule implements android.os.Parcelable {
     ctor public UiccAccessRule(byte[], @Nullable String, long);
     method public int describeContents();
diff --git a/api/test-current.txt b/api/test-current.txt
index 2c7e44d..a060dfc 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -305,6 +305,7 @@
   public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
     method public int describeContents();
     method public long getDuration();
+    method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
     method public long getLastAccessBackgroundTime(int);
     method public long getLastAccessForegroundTime(int);
     method public long getLastAccessTime(int);
@@ -318,13 +319,35 @@
     method public long getLastRejectTime(int, int, int);
     method public int getMode();
     method @NonNull public String getOpStr();
+    method @Deprecated @Nullable public String getProxyPackageName();
+    method @Nullable public String getProxyPackageName(int, int);
+    method @Deprecated public int getProxyUid();
+    method public int getProxyUid(int, int);
+    method public boolean isRunning();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
+  }
+
+  public static final class AppOpsManager.OpFeatureEntry {
+    method public long getDuration();
+    method public long getLastAccessBackgroundTime(int);
+    method public long getLastAccessForegroundTime(int);
+    method public long getLastAccessTime(int);
+    method public long getLastAccessTime(int, int, int);
+    method public long getLastBackgroundDuration(int);
+    method public long getLastDuration(int, int, int);
+    method public long getLastForegroundDuration(int);
+    method public long getLastRejectBackgroundTime(int);
+    method public long getLastRejectForegroundTime(int);
+    method public long getLastRejectTime(int);
+    method public long getLastRejectTime(int, int, int);
+    method @Nullable public String getProxyFeatureId();
+    method @Nullable public String getProxyFeatureId(int, int);
     method @Nullable public String getProxyPackageName();
     method @Nullable public String getProxyPackageName(int, int);
     method public int getProxyUid();
     method public int getProxyUid(int, int);
     method public boolean isRunning();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
   }
 
   public class DownloadManager {
@@ -1100,6 +1123,7 @@
 
   public class LocationManager {
     method @NonNull public String[] getBackgroundThrottlingWhitelist();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @NonNull public String[] getIgnoreSettingsWhitelist();
     method @Nullable @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
     method @NonNull public java.util.List<android.location.LocationRequest> getTestProviderCurrentRequests(String);
@@ -2349,6 +2373,7 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
     field public static final String NAMESPACE_AUTOFILL = "autofill";
     field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
+    field public static final String NAMESPACE_PERMISSIONS = "permissions";
     field public static final String NAMESPACE_PRIVACY = "privacy";
     field public static final String NAMESPACE_ROLLBACK = "rollback";
     field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
@@ -2798,6 +2823,10 @@
     method public void exitBackgroundAudioProcessing(boolean);
   }
 
+  public static class Call.Details {
+    method public String getTelecomCallId();
+  }
+
   public final class CallAudioState implements android.os.Parcelable {
     ctor public CallAudioState(boolean, int, int, @Nullable android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.bluetooth.BluetoothDevice>);
   }
@@ -3105,7 +3134,6 @@
     field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
     field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
     field public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
-    field public static final String USE_BUGREPORT_API = "settings_use_bugreport_api";
   }
 
   public class TimeUtils {
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index e643ab5..b4fdd0b 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -180,11 +180,11 @@
 
     // Note that conditional property enablement/exclusion only applies if
     // the attribute is present. In its absence, all overlays are presumed enabled.
-    if (!overlay_info->requiredSystemPropertyName.empty()
-        && !overlay_info->requiredSystemPropertyValue.empty()) {
+    if (!overlay_info->requiredSystemPropertyName.empty() &&
+        !overlay_info->requiredSystemPropertyValue.empty()) {
       // if property set & equal to value, then include overlay - otherwise skip
-      if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "")
-          != overlay_info->requiredSystemPropertyValue) {
+      if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "") !=
+          overlay_info->requiredSystemPropertyValue) {
         continue;
       }
     }
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
index 1a0d443..924efe5 100644
--- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -34,9 +34,10 @@
   void visit(const IdmapHeader& header) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
-  void visit(const IdmapData::TypeEntry& type_entry) override;
 
  private:
+  void Write(const void* value, size_t length);
+  void Write8(uint8_t value);
   void Write16(uint16_t value);
   void Write32(uint32_t value);
   void WriteString(const StringPiece& value);
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index f2cae58..2639c6f 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -41,6 +41,18 @@
  * # idmap file format changelog
  * ## v1
  * - Identical to idmap v1.
+ * ## v2
+ * - Entries are no longer separated by type into type specific data blocks.
+ * - Added overlay-indexed target resource id lookup capabilities.
+ * - Target and overlay entries are stored as a sparse array in the data block. The target entries
+ *   array maps from target resource id to overlay data type and value and the array is sorted by
+ *   target resource id. The overlay entries array maps from overlay resource id to target resource
+ *   id and the array is sorted by overlay resource id. It is important for both arrays to be sorted
+ *   to allow for O(log(number_of_overlaid_resources)) performance when looking up resource
+ *   mappings at runtime.
+ * - Idmap can now encode a type and value to override a resource without needing a table entry.
+ * - A string pool block is included to retrieve the value of strings that do not have a resource
+ *   table entry.
  */
 
 #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
@@ -125,7 +137,6 @@
   friend Idmap;
   DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
 };
-
 class IdmapData {
  public:
   class Header {
@@ -136,60 +147,51 @@
       return target_package_id_;
     }
 
-    inline uint16_t GetTypeCount() const {
-      return type_count_;
+    inline PackageId GetOverlayPackageId() const {
+      return overlay_package_id_;
+    }
+
+    inline uint32_t GetTargetEntryCount() const {
+      return target_entry_count;
+    }
+
+    inline uint32_t GetOverlayEntryCount() const {
+      return overlay_entry_count;
+    }
+
+    inline uint32_t GetStringPoolIndexOffset() const {
+      return string_pool_index_offset;
+    }
+
+    inline uint32_t GetStringPoolLength() const {
+      return string_pool_len;
     }
 
     void accept(Visitor* v) const;
 
    private:
-    Header() {
-    }
-
     PackageId target_package_id_;
-    uint16_t type_count_;
+    PackageId overlay_package_id_;
+    uint32_t target_entry_count;
+    uint32_t overlay_entry_count;
+    uint32_t string_pool_index_offset;
+    uint32_t string_pool_len;
+    Header() = default;
 
+    friend Idmap;
     friend IdmapData;
     DISALLOW_COPY_AND_ASSIGN(Header);
   };
 
-  class TypeEntry {
-   public:
-    static std::unique_ptr<const TypeEntry> FromBinaryStream(std::istream& stream);
+  struct TargetEntry {
+    ResourceId target_id;
+    TargetValue::DataType data_type;
+    TargetValue::DataValue data_value;
+  };
 
-    inline TypeId GetTargetTypeId() const {
-      return target_type_id_;
-    }
-
-    inline TypeId GetOverlayTypeId() const {
-      return overlay_type_id_;
-    }
-
-    inline uint16_t GetEntryCount() const {
-      return entries_.size();
-    }
-
-    inline uint16_t GetEntryOffset() const {
-      return entry_offset_;
-    }
-
-    inline EntryId GetEntry(size_t i) const {
-      return i < entries_.size() ? entries_[i] : 0xffffu;
-    }
-
-    void accept(Visitor* v) const;
-
-   private:
-    TypeEntry() {
-    }
-
-    TypeId target_type_id_;
-    TypeId overlay_type_id_;
-    uint16_t entry_offset_;
-    std::vector<EntryId> entries_;
-
-    friend IdmapData;
-    DISALLOW_COPY_AND_ASSIGN(TypeEntry);
+  struct OverlayEntry {
+    ResourceId overlay_id;
+    ResourceId target_id;
   };
 
   static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream);
@@ -201,8 +203,16 @@
     return header_;
   }
 
-  inline const std::vector<std::unique_ptr<const TypeEntry>>& GetTypeEntries() const {
-    return type_entries_;
+  inline const std::vector<TargetEntry>& GetTargetEntries() const {
+    return target_entries_;
+  }
+
+  inline const std::vector<OverlayEntry>& GetOverlayEntries() const {
+    return overlay_entries_;
+  }
+
+  inline const void* GetStringPoolData() const {
+    return string_pool_.get();
   }
 
   void accept(Visitor* v) const;
@@ -212,7 +222,9 @@
   }
 
   std::unique_ptr<const Header> header_;
-  std::vector<std::unique_ptr<const TypeEntry>> type_entries_;
+  std::vector<TargetEntry> target_entries_;
+  std::vector<OverlayEntry> overlay_entries_;
+  std::unique_ptr<uint8_t[]> string_pool_;
 
   friend Idmap;
   DISALLOW_COPY_AND_ASSIGN(IdmapData);
@@ -262,7 +274,6 @@
   virtual void visit(const IdmapHeader& header) = 0;
   virtual void visit(const IdmapData& data) = 0;
   virtual void visit(const IdmapData::Header& header) = 0;
-  virtual void visit(const IdmapData::TypeEntry& type_entry) = 0;
 };
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index f0f141a..5dcf217 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -38,13 +38,11 @@
   void visit(const IdmapHeader& header) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
-  void visit(const IdmapData::TypeEntry& type_entry) override;
 
  private:
   std::ostream& stream_;
   std::unique_ptr<const ApkAssets> target_apk_;
   AssetManager2 target_am_;
-  PackageId last_seen_package_id_;
 };
 
 }  // namespace idmap2
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index cd38971..76475ab 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -39,18 +39,20 @@
   void visit(const IdmapHeader& header) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
-  void visit(const IdmapData::TypeEntry& type_entry) override;
 
  private:
+  void print(uint8_t value, const char* fmt, ...);
   void print(uint16_t value, const char* fmt, ...);
   void print(uint32_t value, const char* fmt, ...);
   void print(const std::string& value, const char* fmt, ...);
+  void print_raw(uint32_t length, const char* fmt, ...);
 
   std::ostream& stream_;
   std::unique_ptr<const ApkAssets> target_apk_;
+  std::unique_ptr<const ApkAssets> overlay_apk_;
   AssetManager2 target_am_;
+  AssetManager2 overlay_am_;
   size_t offset_;
-  PackageId last_seen_package_id_;
 };
 
 }  // namespace idmap2
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index abc2df1..de1dbc9 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -37,14 +37,16 @@
 
 namespace utils {
 
+StringPiece DataTypeToString(uint8_t data_type);
+
 struct OverlayManifestInfo {
-  std::string target_package;  // NOLINT(misc-non-private-member-variables-in-classes)
-  std::string target_name;     // NOLINT(misc-non-private-member-variables-in-classes)
-  std::string requiredSystemPropertyName;  // NOLINT(misc-non-private-member-variables-in-classes)
+  std::string target_package;               // NOLINT(misc-non-private-member-variables-in-classes)
+  std::string target_name;                  // NOLINT(misc-non-private-member-variables-in-classes)
+  std::string requiredSystemPropertyName;   // NOLINT(misc-non-private-member-variables-in-classes)
   std::string requiredSystemPropertyValue;  // NOLINT(misc-non-private-member-variables-in-classes)
-  uint32_t resource_mapping;   // NOLINT(misc-non-private-member-variables-in-classes)
-  bool is_static;              // NOLINT(misc-non-private-member-variables-in-classes)
-  int priority = -1;           // NOLINT(misc-non-private-member-variables-in-classes)
+  uint32_t resource_mapping;                // NOLINT(misc-non-private-member-variables-in-classes)
+  bool is_static;                           // NOLINT(misc-non-private-member-variables-in-classes)
+  int priority = -1;                        // NOLINT(misc-non-private-member-variables-in-classes)
 };
 
 Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path,
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index dee2d21..3b0940a 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -24,6 +24,14 @@
 
 namespace android::idmap2 {
 
+void BinaryStreamVisitor::Write(const void* value, size_t length) {
+  stream_.write(reinterpret_cast<const char*>(value), length);
+}
+
+void BinaryStreamVisitor::Write8(uint8_t value) {
+  stream_.write(reinterpret_cast<char*>(&value), sizeof(uint8_t));
+}
+
 void BinaryStreamVisitor::Write16(uint16_t value) {
   uint16_t x = htodl(value);
   stream_.write(reinterpret_cast<char*>(&x), sizeof(uint16_t));
@@ -54,26 +62,28 @@
   WriteString(header.GetOverlayPath());
 }
 
-void BinaryStreamVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
-  // nothing to do
+void BinaryStreamVisitor::visit(const IdmapData& data) {
+  for (const auto& target_entry : data.GetTargetEntries()) {
+    Write32(target_entry.target_id);
+    Write8(target_entry.data_type);
+    Write32(target_entry.data_value);
+  }
+
+  for (const auto& overlay_entry : data.GetOverlayEntries()) {
+    Write32(overlay_entry.overlay_id);
+    Write32(overlay_entry.target_id);
+  }
+
+  Write(data.GetStringPoolData(), data.GetHeader()->GetStringPoolLength());
 }
 
 void BinaryStreamVisitor::visit(const IdmapData::Header& header) {
-  Write16(header.GetTargetPackageId());
-  Write16(header.GetTypeCount());
-}
-
-void BinaryStreamVisitor::visit(const IdmapData::TypeEntry& type_entry) {
-  const uint16_t entryCount = type_entry.GetEntryCount();
-
-  Write16(type_entry.GetTargetTypeId());
-  Write16(type_entry.GetOverlayTypeId());
-  Write16(entryCount);
-  Write16(type_entry.GetEntryOffset());
-  for (uint16_t i = 0; i < entryCount; i++) {
-    EntryId entry_id = type_entry.GetEntry(i);
-    Write32(entry_id != kNoEntry ? static_cast<uint32_t>(entry_id) : kPadding);
-  }
+  Write8(header.GetTargetPackageId());
+  Write8(header.GetOverlayPackageId());
+  Write32(header.GetTargetEntryCount());
+  Write32(header.GetOverlayEntryCount());
+  Write32(header.GetStringPoolIndexOffset());
+  Write32(header.GetStringPoolLength());
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 389ade5..5cb91d7 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -42,30 +42,10 @@
 
 namespace {
 
-class MatchingResources {
- public:
-  void Add(ResourceId target_resid, ResourceId overlay_resid) {
-    TypeId target_typeid = EXTRACT_TYPE(target_resid);
-    if (map_.find(target_typeid) == map_.end()) {
-      map_.emplace(target_typeid, std::set<std::pair<ResourceId, ResourceId>>());
-    }
-    map_[target_typeid].insert(std::make_pair(target_resid, overlay_resid));
-  }
-
-  inline const std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>>& WARN_UNUSED
-  Map() const {
-    return map_;
-  }
-
- private:
-  // target type id -> set { pair { overlay entry id, overlay entry id } }
-  std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>> map_;
-};
-
-bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
-  uint16_t value;
-  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
-    *out = dtohl(value);
+bool WARN_UNUSED Read8(std::istream& stream, uint8_t* out) {
+  uint8_t value;
+  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint8_t))) {
+    *out = value;
     return true;
   }
   return false;
@@ -80,6 +60,15 @@
   return false;
 }
 
+bool WARN_UNUSED ReadBuffer(std::istream& stream, std::unique_ptr<uint8_t[]>* out, size_t length) {
+  auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[length]);
+  if (stream.read(reinterpret_cast<char*>(buffer.get()), length)) {
+    *out = std::move(buffer);
+    return true;
+  }
+  return false;
+}
+
 // a string is encoded as a kIdmapStringLength char array; the array is always null-terminated
 bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
   char buf[kIdmapStringLength];
@@ -162,51 +151,48 @@
 std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
 
-  uint16_t target_package_id16;
-  if (!Read16(stream, &target_package_id16) || !Read16(stream, &idmap_data_header->type_count_)) {
+  if (!Read8(stream, &idmap_data_header->target_package_id_) ||
+      !Read8(stream, &idmap_data_header->overlay_package_id_) ||
+      !Read32(stream, &idmap_data_header->target_entry_count) ||
+      !Read32(stream, &idmap_data_header->overlay_entry_count) ||
+      !Read32(stream, &idmap_data_header->string_pool_index_offset) ||
+      !Read32(stream, &idmap_data_header->string_pool_len)) {
     return nullptr;
   }
-  idmap_data_header->target_package_id_ = target_package_id16;
 
   return std::move(idmap_data_header);
 }
 
-std::unique_ptr<const IdmapData::TypeEntry> IdmapData::TypeEntry::FromBinaryStream(
-    std::istream& stream) {
-  std::unique_ptr<IdmapData::TypeEntry> data(new IdmapData::TypeEntry());
-  uint16_t target_type16;
-  uint16_t overlay_type16;
-  uint16_t entry_count;
-  if (!Read16(stream, &target_type16) || !Read16(stream, &overlay_type16) ||
-      !Read16(stream, &entry_count) || !Read16(stream, &data->entry_offset_)) {
-    return nullptr;
-  }
-  data->target_type_id_ = target_type16;
-  data->overlay_type_id_ = overlay_type16;
-  for (uint16_t i = 0; i < entry_count; i++) {
-    ResourceId resid;
-    if (!Read32(stream, &resid)) {
-      return nullptr;
-    }
-    data->entries_.push_back(resid);
-  }
-
-  return std::move(data);
-}
-
 std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapData> data(new IdmapData());
   data->header_ = IdmapData::Header::FromBinaryStream(stream);
   if (!data->header_) {
     return nullptr;
   }
-  for (size_t type_count = 0; type_count < data->header_->GetTypeCount(); type_count++) {
-    std::unique_ptr<const TypeEntry> type = IdmapData::TypeEntry::FromBinaryStream(stream);
-    if (!type) {
+  // Read the mapping of target resource id to overlay resource value.
+  for (size_t i = 0; i < data->header_->GetTargetEntryCount(); i++) {
+    TargetEntry target_entry{};
+    if (!Read32(stream, &target_entry.target_id) || !Read8(stream, &target_entry.data_type) ||
+        !Read32(stream, &target_entry.data_value)) {
       return nullptr;
     }
-    data->type_entries_.push_back(std::move(type));
+    data->target_entries_.emplace_back(target_entry);
   }
+
+  // Read the mapping of overlay resource id to target resource id.
+  for (size_t i = 0; i < data->header_->GetOverlayEntryCount(); i++) {
+    OverlayEntry overlay_entry{};
+    if (!Read32(stream, &overlay_entry.overlay_id) || !Read32(stream, &overlay_entry.target_id)) {
+      return nullptr;
+    }
+    data->overlay_entries_.emplace_back(overlay_entry);
+  }
+
+  // Read raw string pool bytes.
+  if (!ReadBuffer(stream, &data->string_pool_, data->header_->string_pool_len)) {
+    return nullptr;
+  }
+
   return std::move(data);
 }
 
@@ -247,40 +233,28 @@
     return Error("no resources were overlaid");
   }
 
-  MatchingResources matching_resources;
-  for (const auto mapping : resource_mapping.GetTargetToOverlayMap()) {
-    if (mapping.second.data_type != Res_value::TYPE_REFERENCE) {
-      // The idmap format must change to support non-references.
-      continue;
-    }
-
-    matching_resources.Add(mapping.first, mapping.second.data_value);
+  std::unique_ptr<IdmapData> data(new IdmapData());
+  for (const auto& mappings : resource_mapping.GetTargetToOverlayMap()) {
+    data->target_entries_.emplace_back(IdmapData::TargetEntry{
+        mappings.first, mappings.second.data_type, mappings.second.data_value});
   }
 
-  // encode idmap data
-  std::unique_ptr<IdmapData> data(new IdmapData());
-  const auto types_end = matching_resources.Map().cend();
-  for (auto ti = matching_resources.Map().cbegin(); ti != types_end; ++ti) {
-    auto ei = ti->second.cbegin();
-    std::unique_ptr<IdmapData::TypeEntry> type(new IdmapData::TypeEntry());
-    type->target_type_id_ = EXTRACT_TYPE(ei->first);
-    type->overlay_type_id_ = EXTRACT_TYPE(ei->second);
-    type->entry_offset_ = EXTRACT_ENTRY(ei->first);
-    EntryId last_target_entry = kNoEntry;
-    for (; ei != ti->second.cend(); ++ei) {
-      if (last_target_entry != kNoEntry) {
-        int count = EXTRACT_ENTRY(ei->first) - last_target_entry - 1;
-        type->entries_.insert(type->entries_.end(), count, kNoEntry);
-      }
-      type->entries_.push_back(EXTRACT_ENTRY(ei->second));
-      last_target_entry = EXTRACT_ENTRY(ei->first);
-    }
-    data->type_entries_.push_back(std::move(type));
+  for (const auto& mappings : resource_mapping.GetOverlayToTargetMap()) {
+    data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mappings.first, mappings.second});
   }
 
   std::unique_ptr<IdmapData::Header> data_header(new IdmapData::Header());
   data_header->target_package_id_ = resource_mapping.GetTargetPackageId();
-  data_header->type_count_ = data->type_entries_.size();
+  data_header->overlay_package_id_ = resource_mapping.GetOverlayPackageId();
+  data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size());
+  data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size());
+  data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset();
+
+  const auto string_pool_data = resource_mapping.GetStringPoolData();
+  data_header->string_pool_len = string_pool_data.second;
+  data->string_pool_ = std::unique_ptr<uint8_t[]>(new uint8_t[data_header->string_pool_len]);
+  memcpy(data->string_pool_.get(), string_pool_data.first, data_header->string_pool_len);
+
   data->header_ = std::move(data_header);
   return {std::move(data)};
 }
@@ -367,25 +341,16 @@
   v->visit(*this);
 }
 
-void IdmapData::TypeEntry::accept(Visitor* v) const {
-  assert(v != nullptr);
-  v->visit(*this);
-}
-
 void IdmapData::accept(Visitor* v) const {
   assert(v != nullptr);
-  v->visit(*this);
   header_->accept(v);
-  auto end = type_entries_.cend();
-  for (auto iter = type_entries_.cbegin(); iter != end; ++iter) {
-    (*iter)->accept(v);
-  }
+  v->visit(*this);
 }
 
 void Idmap::accept(Visitor* v) const {
   assert(v != nullptr);
-  v->visit(*this);
   header_->accept(v);
+  v->visit(*this);
   auto end = data_.cend();
   for (auto iter = data_.cbegin(); iter != end; ++iter) {
     (*iter)->accept(v);
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index fbf2c77..a662aa5 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -41,29 +41,33 @@
   }
 }
 
-void PrettyPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
-}
-
 void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED) {
-  last_seen_package_id_ = header.GetTargetPackageId();
 }
 
-void PrettyPrintVisitor::visit(const IdmapData::TypeEntry& type_entry) {
+void PrettyPrintVisitor::visit(const IdmapData& data) {
   const bool target_package_loaded = !target_am_.GetApkAssets().empty();
-  for (uint16_t i = 0; i < type_entry.GetEntryCount(); i++) {
-    const EntryId entry = type_entry.GetEntry(i);
-    if (entry == kNoEntry) {
-      continue;
+  const ResStringPool string_pool(data.GetStringPoolData(),
+                                  data.GetHeader()->GetStringPoolLength());
+  const size_t string_pool_offset = data.GetHeader()->GetStringPoolIndexOffset();
+
+  for (auto& target_entry : data.GetTargetEntries()) {
+    stream_ << base::StringPrintf("0x%08x ->", target_entry.target_id);
+
+    if (target_entry.data_type != Res_value::TYPE_REFERENCE &&
+        target_entry.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
+      stream_ << " " << utils::DataTypeToString(target_entry.data_type);
     }
 
-    const ResourceId target_resid =
-        RESID(last_seen_package_id_, type_entry.GetTargetTypeId(), type_entry.GetEntryOffset() + i);
-    const ResourceId overlay_resid =
-        RESID(last_seen_package_id_, type_entry.GetOverlayTypeId(), entry);
+    if (target_entry.data_type == Res_value::TYPE_STRING) {
+      stream_ << " \""
+              << string_pool.string8ObjectAt(target_entry.data_value - string_pool_offset).c_str()
+              << "\"";
+    } else {
+      stream_ << " " << base::StringPrintf("0x%08x", target_entry.data_value);
+    }
 
-    stream_ << base::StringPrintf("0x%08x -> 0x%08x", target_resid, overlay_resid);
     if (target_package_loaded) {
-      Result<std::string> name = utils::ResToTypeEntryName(target_am_, target_resid);
+      Result<std::string> name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
       if (name) {
         stream_ << " " << *name;
       }
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index dd14fd4..13973d6 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -47,46 +47,94 @@
   if (target_apk_) {
     target_am_.SetApkAssets({target_apk_.get()});
   }
+
+  overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string());
+  if (overlay_apk_) {
+    overlay_am_.SetApkAssets({overlay_apk_.get()});
+  }
 }
 
 void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
+  const bool target_package_loaded = !target_am_.GetApkAssets().empty();
+  const bool overlay_package_loaded = !overlay_am_.GetApkAssets().empty();
+
+  for (auto& target_entry : data.GetTargetEntries()) {
+    Result<std::string> target_name(Error(""));
+    if (target_package_loaded) {
+      target_name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
+    }
+    if (target_name) {
+      print(target_entry.target_id, "target id: %s", target_name->c_str());
+    } else {
+      print(target_entry.target_id, "target id");
+    }
+
+    print(target_entry.data_type, "type: %s",
+          utils::DataTypeToString(target_entry.data_type).data());
+
+    Result<std::string> overlay_name(Error(""));
+    if (overlay_package_loaded && (target_entry.data_type == Res_value::TYPE_REFERENCE ||
+                                   target_entry.data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) {
+      overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.data_value);
+    }
+    if (overlay_name) {
+      print(target_entry.data_value, "value: %s", overlay_name->c_str());
+    } else {
+      print(target_entry.data_value, "value");
+    }
+  }
+
+  for (auto& overlay_entry : data.GetOverlayEntries()) {
+    Result<std::string> overlay_name(Error(""));
+    if (overlay_package_loaded) {
+      overlay_name = utils::ResToTypeEntryName(overlay_am_, overlay_entry.overlay_id);
+    }
+
+    if (overlay_name) {
+      print(overlay_entry.overlay_id, "overlay id: %s", overlay_name->c_str());
+    } else {
+      print(overlay_entry.overlay_id, "overlay id");
+    }
+
+    Result<std::string> target_name(Error(""));
+    if (target_package_loaded) {
+      target_name = utils::ResToTypeEntryName(target_am_, overlay_entry.target_id);
+    }
+
+    if (target_name) {
+      print(overlay_entry.target_id, "target id: %s", target_name->c_str());
+    } else {
+      print(overlay_entry.target_id, "target id");
+    }
+  }
+
+  const size_t string_pool_length = data.GetHeader()->GetStringPoolLength();
+  if (string_pool_length > 0) {
+    print_raw(string_pool_length, "%zu raw string pool bytes", string_pool_length);
+  }
 }
 
 void RawPrintVisitor::visit(const IdmapData::Header& header) {
-  print(static_cast<uint16_t>(header.GetTargetPackageId()), "target package id");
-  print(header.GetTypeCount(), "type count");
-  last_seen_package_id_ = header.GetTargetPackageId();
+  print(header.GetTargetPackageId(), "target package id");
+  print(header.GetOverlayPackageId(), "overlay package id");
+  print(header.GetTargetEntryCount(), "target entry count");
+  print(header.GetOverlayEntryCount(), "overlay entry count");
+  print(header.GetStringPoolIndexOffset(), "string pool index offset");
+  print(header.GetStringPoolLength(), "string pool byte length");
 }
 
-void RawPrintVisitor::visit(const IdmapData::TypeEntry& type_entry) {
-  const bool target_package_loaded = !target_am_.GetApkAssets().empty();
+// NOLINTNEXTLINE(cert-dcl50-cpp)
+void RawPrintVisitor::print(uint8_t value, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string comment;
+  base::StringAppendV(&comment, fmt, ap);
+  va_end(ap);
 
-  print(static_cast<uint16_t>(type_entry.GetTargetTypeId()), "target type");
-  print(static_cast<uint16_t>(type_entry.GetOverlayTypeId()), "overlay type");
-  print(static_cast<uint16_t>(type_entry.GetEntryCount()), "entry count");
-  print(static_cast<uint16_t>(type_entry.GetEntryOffset()), "entry offset");
+  stream_ << base::StringPrintf("%08zx:       %02x", offset_, value) << "  " << comment
+          << std::endl;
 
-  for (uint16_t i = 0; i < type_entry.GetEntryCount(); i++) {
-    const EntryId entry = type_entry.GetEntry(i);
-    if (entry == kNoEntry) {
-      print(kPadding, "no entry");
-    } else {
-      const ResourceId target_resid = RESID(last_seen_package_id_, type_entry.GetTargetTypeId(),
-                                            type_entry.GetEntryOffset() + i);
-      const ResourceId overlay_resid =
-          RESID(last_seen_package_id_, type_entry.GetOverlayTypeId(), entry);
-      Result<std::string> name(Error(""));
-      if (target_package_loaded) {
-        name = utils::ResToTypeEntryName(target_am_, target_resid);
-      }
-      if (name) {
-        print(static_cast<uint32_t>(entry), "0x%08x -> 0x%08x %s", target_resid, overlay_resid,
-              name->c_str());
-      } else {
-        print(static_cast<uint32_t>(entry), "0x%08x -> 0x%08x", target_resid, overlay_resid);
-      }
-    }
-  }
+  offset_ += sizeof(uint8_t);
 }
 
 // NOLINTNEXTLINE(cert-dcl50-cpp)
@@ -123,10 +171,23 @@
   base::StringAppendV(&comment, fmt, ap);
   va_end(ap);
 
-  stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment << ": " << value
+  stream_ << base::StringPrintf("%08zx: ", offset_) << "........  " << comment << ": " << value
           << std::endl;
 
   offset_ += kIdmapStringLength;
 }
 
+// NOLINTNEXTLINE(cert-dcl50-cpp)
+void RawPrintVisitor::print_raw(uint32_t length, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string comment;
+  base::StringAppendV(&comment, fmt, ap);
+  va_end(ap);
+
+  stream_ << base::StringPrintf("%08zx: ", offset_) << "........  " << comment << std::endl;
+
+  offset_ += length;
+}
+
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index 95ae626..651d20f 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -192,9 +192,14 @@
     // Only rewrite resources defined within the overlay package to their corresponding target
     // resource ids at runtime.
     bool rewrite_overlay_reference =
-        (overlay_resource->dataType == Res_value::TYPE_REFERENCE)
+        (overlay_resource->dataType == Res_value::TYPE_REFERENCE ||
+         overlay_resource->dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
             ? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data)
             : false;
+    
+    if (rewrite_overlay_reference) {
+      overlay_resource->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+    }
 
     resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data,
                                 rewrite_overlay_reference);
@@ -224,7 +229,7 @@
     }
 
     resource_mapping.AddMapping(target_resource, Res_value::TYPE_REFERENCE, overlay_resid,
-                                /* rewrite_overlay_reference */ true);
+                                /* rewrite_overlay_reference */ false);
   }
 
   return resource_mapping;
@@ -378,7 +383,8 @@
 
   target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
 
-  if (rewrite_overlay_reference && data_type == Res_value::TYPE_REFERENCE) {
+  if (rewrite_overlay_reference &&
+      (data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) {
     overlay_map_.insert(std::make_pair(data_value, target_resource));
   }
 
@@ -394,8 +400,8 @@
   const TargetValue value = target_iter->second;
   target_map_.erase(target_iter);
 
-  // Remove rewriting of overlay resource id to target resource id.
-  if (value.data_type != Res_value::TYPE_REFERENCE) {
+  if (value.data_type != Res_value::TYPE_REFERENCE &&
+      value.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
     return;
   }
 
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
index 9d32692..a5df746 100644
--- a/cmds/idmap2/libidmap2/ResourceUtils.cpp
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -33,6 +33,40 @@
 
 namespace android::idmap2::utils {
 
+StringPiece DataTypeToString(uint8_t data_type) {
+  switch (data_type) {
+    case Res_value::TYPE_NULL:
+      return "null";
+    case Res_value::TYPE_REFERENCE:
+      return "reference";
+    case Res_value::TYPE_ATTRIBUTE:
+      return "attribute";
+    case Res_value::TYPE_STRING:
+      return "string";
+    case Res_value::TYPE_FLOAT:
+      return "float";
+    case Res_value::TYPE_DIMENSION:
+      return "dimension";
+    case Res_value::TYPE_FRACTION:
+      return "fraction";
+    case Res_value::TYPE_DYNAMIC_REFERENCE:
+      return "reference (dynamic)";
+    case Res_value::TYPE_DYNAMIC_ATTRIBUTE:
+      return "attribute (dynamic)";
+    case Res_value::TYPE_INT_DEC:
+    case Res_value::TYPE_INT_HEX:
+      return "integer";
+    case Res_value::TYPE_INT_BOOLEAN:
+      return "boolean";
+    case Res_value::TYPE_INT_COLOR_ARGB8:
+    case Res_value::TYPE_INT_COLOR_RGB8:
+    case Res_value::TYPE_INT_COLOR_RGB4:
+      return "color";
+    default:
+      return "unknown";
+  }
+}
+
 Result<std::string> ResToTypeEntryName(const AssetManager2& am, uint32_t resid) {
   AssetManager2::ResourceName name;
   if (!am.GetResourceName(resid, &name)) {
@@ -129,7 +163,7 @@
     info.requiredSystemPropertyName = *result_str;
   }
 
-   if (auto result_str = overlay_it->GetAttributeStringValue("requiredSystemPropertyValue")) {
+  if (auto result_str = overlay_it->GetAttributeStringValue("requiredSystemPropertyValue")) {
     info.requiredSystemPropertyValue = *result_str;
   }
 
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 43fdc9a..db4778c 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -18,6 +18,7 @@
 #include <sstream>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "TestHelpers.h"
 #include "androidfw/ApkAssets.h"
@@ -52,112 +53,39 @@
   ASSERT_EQ(idmap1->GetData().size(), 1U);
   ASSERT_EQ(idmap1->GetData().size(), idmap2->GetData().size());
 
-  const auto& data1 = idmap1->GetData()[0];
-  const auto& data2 = idmap2->GetData()[0];
+  const std::vector<std::unique_ptr<const IdmapData>>& data_blocks1 = idmap1->GetData();
+  ASSERT_EQ(data_blocks1.size(), 1U);
+  const std::unique_ptr<const IdmapData>& data1 = data_blocks1[0];
+  ASSERT_THAT(data1, NotNull());
 
-  ASSERT_EQ(data1->GetHeader()->GetTargetPackageId(), data2->GetHeader()->GetTargetPackageId());
-  ASSERT_EQ(data1->GetTypeEntries().size(), 2U);
-  ASSERT_EQ(data1->GetTypeEntries().size(), data2->GetTypeEntries().size());
-  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(0), data2->GetTypeEntries()[0]->GetEntry(0));
-  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(1), data2->GetTypeEntries()[0]->GetEntry(1));
-  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(2), data2->GetTypeEntries()[0]->GetEntry(2));
-  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(0), data2->GetTypeEntries()[1]->GetEntry(0));
-  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(1), data2->GetTypeEntries()[1]->GetEntry(1));
-  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(2), data2->GetTypeEntries()[1]->GetEntry(2));
-}
+  const std::vector<std::unique_ptr<const IdmapData>>& data_blocks2 = idmap2->GetData();
+  ASSERT_EQ(data_blocks2.size(), 1U);
+  const std::unique_ptr<const IdmapData>& data2 = data_blocks2[0];
+  ASSERT_THAT(data2, NotNull());
 
-TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
+  const auto& target_entries1 = data1->GetTargetEntries();
+  const auto& target_entries2 = data2->GetTargetEntries();
+  ASSERT_EQ(target_entries1.size(), target_entries2.size());
+  ASSERT_EQ(target_entries1[0].target_id, target_entries2[0].target_id);
+  ASSERT_EQ(target_entries1[0].data_value, target_entries2[0].data_value);
 
-  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
+  ASSERT_EQ(target_entries1[1].target_id, target_entries2[1].target_id);
+  ASSERT_EQ(target_entries1[1].data_value, target_entries2[1].data_value);
 
-  const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
-                                          /* enforce_overlayable */ true);
-  ASSERT_TRUE(idmap);
+  ASSERT_EQ(target_entries1[2].target_id, target_entries2[2].target_id);
+  ASSERT_EQ(target_entries1[2].data_value, target_entries2[2].data_value);
 
-  std::stringstream stream;
-  BinaryStreamVisitor visitor(stream);
-  (*idmap)->accept(&visitor);
-  const std::string str = stream.str();
-  const StringPiece data(str);
-  std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(data);
-  ASSERT_THAT(loaded_idmap, NotNull());
-  ASSERT_EQ(loaded_idmap->TargetPackageId(), 0x7f);
+  const auto& overlay_entries1 = data1->GetOverlayEntries();
+  const auto& overlay_entries2 = data2->GetOverlayEntries();
+  ASSERT_EQ(overlay_entries1.size(), overlay_entries2.size());
+  ASSERT_EQ(overlay_entries1[0].overlay_id, overlay_entries2[0].overlay_id);
+  ASSERT_EQ(overlay_entries1[0].target_id, overlay_entries2[0].target_id);
 
-  const IdmapEntry_header* header = loaded_idmap->GetEntryMapForType(0x01);
-  ASSERT_THAT(header, NotNull());
+  ASSERT_EQ(overlay_entries1[1].overlay_id, overlay_entries2[1].overlay_id);
+  ASSERT_EQ(overlay_entries1[1].target_id, overlay_entries2[1].target_id);
 
-  EntryId entry;
-  bool success = LoadedIdmap::Lookup(header, 0x0000, &entry);
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0000);
-
-  header = loaded_idmap->GetEntryMapForType(0x02);
-  ASSERT_THAT(header, NotNull());
-
-  success = LoadedIdmap::Lookup(header, 0x0000, &entry);  // string/a
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0001, &entry);  // string/b
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0002, &entry);  // string/c
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0003, &entry);  // string/policy_odm
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0004, &entry);  // string/policy_oem
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0005, &entry);  // string/other
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0006, &entry);  // string/not_overlayable
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0007, &entry);  // string/policy_product
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0008, &entry);  // string/policy_public
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0009, &entry);  // string/policy_system
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000a, &entry);  // string/policy_system_vendor
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000b, &entry);  // string/policy_signature
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000c, &entry);  // string/str1
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0000);
-
-  success = LoadedIdmap::Lookup(header, 0x000d, &entry);  // string/str2
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x000e, &entry);  // string/str3
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0001);
-
-  success = LoadedIdmap::Lookup(header, 0x000f, &entry);  // string/str4
-  ASSERT_TRUE(success);
-  ASSERT_EQ(entry, 0x0002);
-
-  success = LoadedIdmap::Lookup(header, 0x0010, &entry);  // string/x
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0011, &entry);  // string/y
-  ASSERT_FALSE(success);
-
-  success = LoadedIdmap::Lookup(header, 0x0012, &entry);  // string/z
-  ASSERT_FALSE(success);
+  ASSERT_EQ(overlay_entries1[2].overlay_id, overlay_entries2[2].overlay_id);
+  ASSERT_EQ(overlay_entries1[2].target_id, overlay_entries2[2].target_id);
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 8a48f4b..b535f30 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -131,7 +131,6 @@
   ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020000 string/str1"), std::string::npos);
   ASSERT_NE(result->stdout.find("0x7f02000e -> 0x7f020001 string/str3"), std::string::npos);
   ASSERT_NE(result->stdout.find("0x7f02000f -> 0x7f020002 string/str4"), std::string::npos);
-  ASSERT_EQ(result->stdout.find("00000210:     007f  target package id"), std::string::npos);
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
@@ -142,7 +141,6 @@
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
   ASSERT_NE(result->stdout.find("00000000: 504d4449  magic"), std::string::npos);
-  ASSERT_NE(result->stdout.find("00000210:     007f  target package id"), std::string::npos);
 
   // clang-format off
   result = ExecuteBinary({"idmap2",
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 47e5b17..cd816dd 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -31,11 +31,21 @@
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Idmap.h"
 
+using android::Res_value;
 using ::testing::IsNull;
 using ::testing::NotNull;
 
 namespace android::idmap2 {
 
+#define ASSERT_TARGET_ENTRY(entry, target_resid, type, value) \
+  ASSERT_EQ(entry.target_id, target_resid);                   \
+  ASSERT_EQ(entry.data_type, type);                           \
+  ASSERT_EQ(entry.data_value, value)
+
+#define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \
+  ASSERT_EQ(entry.overlay_id, overlay_resid);                    \
+  ASSERT_EQ(entry.target_id, target_resid)
+
 TEST(IdmapTests, TestCanonicalIdmapPathFor) {
   ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
             "/foo/vendor@overlay@bar.apk@idmap");
@@ -47,11 +57,11 @@
   std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
   ASSERT_THAT(header, NotNull());
   ASSERT_EQ(header->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(header->GetVersion(), 0x01U);
+  ASSERT_EQ(header->GetVersion(), 0x02U);
   ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
-  ASSERT_EQ(header->GetTargetPath().to_string(), "target.apk");
-  ASSERT_EQ(header->GetOverlayPath().to_string(), "overlay.apk");
+  ASSERT_EQ(header->GetTargetPath().to_string(), "targetX.apk");
+  ASSERT_EQ(header->GetOverlayPath().to_string(), "overlayX.apk");
 }
 
 TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
@@ -73,23 +83,8 @@
 
   std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
   ASSERT_THAT(header, NotNull());
-  ASSERT_EQ(header->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(header->GetTypeCount(), 2U);
-}
-
-TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
-  const size_t offset = 0x214;
-  std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
-                  idmap_raw_data_len - offset);
-  std::istringstream stream(raw);
-
-  std::unique_ptr<const IdmapData::TypeEntry> data = IdmapData::TypeEntry::FromBinaryStream(stream);
-  ASSERT_THAT(data, NotNull());
-  ASSERT_EQ(data->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(data->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(data->GetEntryCount(), 1U);
-  ASSERT_EQ(data->GetEntryOffset(), 0U);
-  ASSERT_EQ(data->GetEntry(0), 0U);
+  ASSERT_EQ(header->GetTargetEntryCount(), 0x03);
+  ASSERT_EQ(header->GetOverlayEntryCount(), 0x03);
 }
 
 TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
@@ -100,24 +95,21 @@
 
   std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
   ASSERT_THAT(data, NotNull());
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
 
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x01 /* Res_value::TYPE_REFERENCE */,
+                      0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x01 /* Res_value::TYPE_REFERENCE */,
+                      0x7f030000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x01 /* Res_value::TYPE_REFERENCE */,
+                      0x7f030001);
 
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 3U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020000, 0x7f020000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f030000, 0x7f030000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f030001, 0x7f030002);
 }
 
 TEST(IdmapTests, CreateIdmapFromBinaryStream) {
@@ -130,34 +122,29 @@
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x02U);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
-  ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "target.apk");
-  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlay.apk");
+  ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "targetX.apk");
+  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlayX.apk");
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
   ASSERT_EQ(dataBlocks.size(), 1U);
 
   const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
+  ASSERT_THAT(data, NotNull());
 
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, Res_value::TYPE_REFERENCE, 0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, Res_value::TYPE_REFERENCE, 0x7f030000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, Res_value::TYPE_REFERENCE, 0x7f030001);
 
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 3U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(target_entries.size(), 3U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020000, 0x7f020000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f030000, 0x7f030000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f030001, 0x7f030002);
 }
 
 TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
@@ -169,300 +156,140 @@
   ASSERT_FALSE(result);
 }
 
-void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
-                 const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
-                 std::unique_ptr<const Idmap>* out_idmap) {
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
-  ASSERT_THAT(target_apk, NotNull());
-
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  auto result =
-      Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, enforce_overlayable);
-  *out_idmap = result ? std::move(*result) : nullptr;
-}
-
-TEST(IdmapTests, CreateIdmapFromApkAssets) {
-  std::unique_ptr<const Idmap> idmap;
+TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) {
   std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
   std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
+
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                           /* enforce_overlayable */ true);
+  ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
+  auto& idmap = *idmap_result;
+  ASSERT_THAT(idmap, NotNull());
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x02U);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xc054fb26);
   ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
-  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
-
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 12U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
-  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
 }
 
-// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
-  std::unique_ptr<const Idmap> idmap;
+Result<std::unique_ptr<const IdmapData>> TestIdmapDataFromApkAssets(
+    const android::StringPiece& local_target_apk_path,
+    const android::StringPiece& local_overlay_apk_path, const OverlayManifestInfo& overlay_info,
+    const PolicyBitmask& fulfilled_policies, bool enforce_overlayable) {
+  const std::string target_apk_path(GetTestDataPath() + local_target_apk_path.data());
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  if (!target_apk) {
+    return Error(R"(Failed to load target apk "%s")", target_apk_path.data());
+  }
+
+  const std::string overlay_apk_path(GetTestDataPath() + local_overlay_apk_path.data());
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  if (!overlay_apk) {
+    return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
+  }
+
+  auto mapping = ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, overlay_info,
+                                                fulfilled_policies, enforce_overlayable);
+
+  if (!mapping) {
+    return mapping.GetError();
+  }
+
+  return IdmapData::FromResourceMapping(*mapping);
+}
+
+TEST(IdmapTests, CreateIdmapDataFromApkAssets) {
   std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
+
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+                                           /* enforce_overlayable */ true);
+  ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
+  auto& idmap = *idmap_result;
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
   ASSERT_EQ(dataBlocks.size(), 1U);
 
   const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+  ASSERT_THAT(data, NotNull());
 
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 4U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f010000);
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000);
+  ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001);
+  ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002);
 
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 8U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);   // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0001U);   // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0002U);   // string/policy_system_vendor
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(target_entries.size(), 4U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f010000, 0x7f010000);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f020000, 0x7f02000c);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f020001, 0x7f02000e);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x7f020002, 0x7f02000f);
 }
 
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
+TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0x7f030001;  // xml/overlays_different_packages
+  auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
+                                               PolicyFlags::POLICY_PUBLIC,
+                                               /* enforce_overlayable */ false);
 
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
+  ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
+  auto& data = *idmap_data;
 
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 2U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f02000c, Res_value::TYPE_REFERENCE,
+                      0x0104000a);  // string/str1 -> android:string/ok
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE,
+                      0x7f020001);  // string/str3 -> string/str4
 
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 9U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/policy_signature
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(overlay_entries.size(), 1U);
+  ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020001, 0x7f02000e);  // string/str3 <- string/str4
 }
 
-// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path =
-      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
+TEST(IdmapTests, CreateIdmapDataInlineResources) {
+  OverlayManifestInfo info{};
+  info.target_package = "test.target";
+  info.target_name = "TestResources";
+  info.resource_mapping = 0x7f030002;  // xml/overlays_inline
+  auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
+                                               PolicyFlags::POLICY_PUBLIC,
+                                               /* enforce_overlayable */ false);
 
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
+  ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
+  auto& data = *idmap_data;
 
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+  constexpr size_t overlay_string_pool_size = 8U;
+  const auto& target_entries = data->GetTargetEntries();
+  ASSERT_EQ(target_entries.size(), 2U);
+  ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_INT_DEC,
+                      73U);  // integer/int1 -> 73
+  ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_STRING,
+                      overlay_string_pool_size + 0U);  // string/str1 -> "Hello World"
 
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 8U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0005U);   // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0007U);   // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0008U);   // string/policy_system_vendor
-}
-
-// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
-  std::string overlay_apk_path =
-      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path,
-              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ false, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 9U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
-  ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/policy_odm
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_oem
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/other
-  ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/policy_product
-  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(7), 0x0007U);  // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(8), 0x0008U);  // string/policy_system_vendor
-}
-
-// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ false, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 2U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/int1
-
-  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
-  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
-  ASSERT_EQ(types[1]->GetEntryOffset(), 12U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);   // string/str1
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);  // string/str2
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);   // string/str3
-  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);   // string/str4
-}
-
-// Overlays that are not pre-installed and are not signed with the same signature as the target
-// cannot overlay packages that have not defined overlayable resources.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
-  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, IsNull());
-}
-
-// Overlays that are pre-installed or are signed with the same signature as the target can overlay
-// packages that have not defined overlayable resources.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
-  std::unique_ptr<const Idmap> idmap;
-  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
-  std::string overlay_apk_path =
-      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
-
-  auto CheckEntries = [&]() -> void {
-    const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-    ASSERT_EQ(dataBlocks.size(), 1U);
-
-    const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-    ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-    ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-    const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-    ASSERT_EQ(types.size(), 1U);
-
-    ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-    ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-    ASSERT_EQ(types[0]->GetEntryCount(), 9U);
-    ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
-    ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
-    ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/policy_odm
-    ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_oem
-    ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/other
-    ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/policy_product
-    ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_public
-    ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_signature
-    ASSERT_EQ(types[0]->GetEntry(7), 0x0007U);  // string/policy_system
-    ASSERT_EQ(types[0]->GetEntry(8), 0x0008U);  // string/policy_system_vendor
-  };
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_ODM_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
-
-  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_OEM_PARTITION,
-              /* enforce_overlayable */ true, &idmap);
-  ASSERT_THAT(idmap, NotNull());
-  CheckEntries();
+  const auto& overlay_entries = data->GetOverlayEntries();
+  ASSERT_EQ(overlay_entries.size(), 0U);
 }
 
 TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
@@ -602,10 +429,6 @@
     stream_ << "TestVisitor::visit(IdmapData::Header)" << std::endl;
   }
 
-  void visit(const IdmapData::TypeEntry& idmap ATTRIBUTE_UNUSED) override {
-    stream_ << "TestVisitor::visit(IdmapData::TypeEntry)" << std::endl;
-  }
-
  private:
   std::ostream& stream_;
 };
@@ -622,12 +445,10 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_EQ(test_stream.str(),
-            "TestVisitor::visit(Idmap)\n"
             "TestVisitor::visit(IdmapHeader)\n"
-            "TestVisitor::visit(IdmapData)\n"
+            "TestVisitor::visit(Idmap)\n"
             "TestVisitor::visit(IdmapData::Header)\n"
-            "TestVisitor::visit(IdmapData::TypeEntry)\n"
-            "TestVisitor::visit(IdmapData::TypeEntry)\n");
+            "TestVisitor::visit(IdmapData)\n");
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index c243d74..d387880 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -47,11 +47,21 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_NE(stream.str().find("00000000: 504d4449  magic\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("00000004: 00000001  version\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000004: 00000002  version\n"), std::string::npos);
   ASSERT_NE(stream.str().find("00000008: 76a20829  target crc\n"), std::string::npos);
   ASSERT_NE(stream.str().find("0000000c: c054fb26  overlay crc\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("0000021c: 00000000  0x7f010000 -> 0x7f010000 integer/int1\n"),
+  ASSERT_NE(stream.str().find("00000210:       7f  target package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000211:       7f  overlay package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000212: 00000004  target entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000216: 00000004  overlay entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021a: 00000008  string pool index offset\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021e: 000000b4  string pool byte length\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000222: 7f010000  target id: integer/int1\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000226:       07  type: reference (dynamic)\n"),
             std::string::npos);
+  ASSERT_NE(stream.str().find("00000227: 7f010000  value: integer/int1\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000246: 7f010000  overlay id: integer/int1\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000024a: 7f010000  target id: integer/int1\n"), std::string::npos);
 }
 
 TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
@@ -68,10 +78,21 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_NE(stream.str().find("00000000: 504d4449  magic\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("00000004: 00000001  version\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000004: 00000002  version\n"), std::string::npos);
   ASSERT_NE(stream.str().find("00000008: 00001234  target crc\n"), std::string::npos);
   ASSERT_NE(stream.str().find("0000000c: 00005678  overlay crc\n"), std::string::npos);
-  ASSERT_NE(stream.str().find("0000021c: 00000000  0x7f020000 -> 0x7f020000\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000210:       7f  target package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000211:       7f  overlay package id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000212: 00000003  target entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000216: 00000003  overlay entry count\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021a: 00000000  string pool index offset\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021e: 00000000  string pool byte length\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000222: 7f020000  target id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000226:       01  type: reference\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000227: 7f020000  value\n"), std::string::npos);
+
+  ASSERT_NE(stream.str().find("0000023d: 7f020000  overlay id\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000241: 7f020000  target id\n"), std::string::npos);
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index 1ef41de..64304f6 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -27,6 +27,7 @@
 #include "gtest/gtest.h"
 #include "idmap2/ResourceMapping.h"
 
+using android::Res_value;
 using android::idmap2::utils::ExtractOverlayManifestInfo;
 
 namespace android::idmap2 {
@@ -109,14 +110,14 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
-  ASSERT_RESULT(MappingExists(res, 0x7f010000, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // integer/int1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020000,
-                              true /* rewrite */));  // string/str1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
-                              true /* rewrite */));  // string/str3
-  ASSERT_RESULT(MappingExists(res, 0x7f02000f, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020002,
-                              true /* rewrite */));  // string/str4
+  ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // integer/int1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000,
+                              false /* rewrite */));  // string/str1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001,
+                              false /* rewrite */));  // string/str3
+  ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002,
+                              false /* rewrite */));  // string/str4
 }
 
 TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
@@ -131,15 +132,15 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020002,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002,
                               true /* rewrite */));  // string/str1 -> string/str4
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020000,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000,
                               true /* rewrite */));  // string/str3 -> string/str1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000f, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001,
                               true /* rewrite */));  // string/str4 -> string/str3
 }
 
-TEST(ResourceMappingTests, DoNotRewriteNonResourceMapping) {
+TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
   OverlayManifestInfo info{};
   info.target_package = "test.target";
   info.target_name = "TestResources";
@@ -152,9 +153,9 @@
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
   ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U);
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x0104000a,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x0104000a,
                               false /* rewrite */));  // string/str1 -> android:string/ok
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001,
                               true /* rewrite */));  // string/str3 -> string/str4
 }
 
@@ -172,10 +173,10 @@
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
   ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x03 /* Res_value::TYPE_STRING */,
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_STRING,
                               overlay_string_pool_size + 0U,
                               false /* rewrite */));  // string/str1 -> "Hello World"
-  ASSERT_RESULT(MappingExists(res, 0x7f010000, 0x10 /* Res_value::TYPE_INT_DEC */, 73U,
+  ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_INT_DEC, 73U,
                               false /* rewrite */));  // string/str1 -> "Hello World"
 }
 
@@ -188,12 +189,12 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // string/policy_public
-  ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010001,
-                              true /* rewrite */));  // string/policy_system
-  ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010002,
-                              true /* rewrite */));  // string/policy_system_vendor
+  ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // string/policy_public
+  ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010001,
+                              false /* rewrite */));  // string/policy_system
+  ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010002,
+                              false /* rewrite */));  // string/policy_system_vendor
 }
 
 // Resources that are not declared as overlayable and resources that a protected by policies the
@@ -207,12 +208,12 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
-  ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010005,
-                              true /* rewrite */));  // string/policy_public
-  ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010007,
-                              true /* rewrite */));  // string/policy_system
-  ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010008,
-                              true /* rewrite */));  // string/policy_system_vendor
+  ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
+                              false /* rewrite */));  // string/policy_public
+  ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
+                              false /* rewrite */));  // string/policy_system
+  ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
+                              false /* rewrite */));  // string/policy_system_vendor
 }
 
 // Resources that are not declared as overlayable and resources that a protected by policies the
@@ -227,24 +228,24 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 9U);
-  ASSERT_RESULT(MappingExists(res, 0x7f020003, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // string/not_overlayable
-  ASSERT_RESULT(MappingExists(res, 0x7f020004, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010001,
-                              true /* rewrite */));  // string/other
-  ASSERT_RESULT(MappingExists(res, 0x7f020005, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010002,
-                              true /* rewrite */));  // string/policy_odm
-  ASSERT_RESULT(MappingExists(res, 0x7f020006, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010003,
-                              true /* rewrite */));  // string/policy_oem
-  ASSERT_RESULT(MappingExists(res, 0x7f020007, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010004,
-                              true /* rewrite */));  // string/policy_product
-  ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010005,
-                              true /* rewrite */));  // string/policy_public
-  ASSERT_RESULT(MappingExists(res, 0x7f020009, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010006,
-                              true /* rewrite */));  // string/policy_signature
-  ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010007,
-                              true /* rewrite */));  // string/policy_system
-  ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010008,
-                              true /* rewrite */));  // string/policy_system_vendor
+  ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // string/not_overlayable
+  ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
+                              false /* rewrite */));  // string/other
+  ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
+                              false /* rewrite */));  // string/policy_odm
+  ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
+                              false /* rewrite */));  // string/policy_oem
+  ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
+                              false /* rewrite */));  // string/policy_product
+  ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
+                              false /* rewrite */));  // string/policy_public
+  ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
+                              false /* rewrite */));  // string/policy_signature
+  ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
+                              false /* rewrite */));  // string/policy_system
+  ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
+                              false /* rewrite */));  // string/policy_system_vendor
 }
 
 // Overlays that do not target an <overlayable> tag can overlay resources defined within any
@@ -257,14 +258,14 @@
   ASSERT_TRUE(resources) << resources.GetErrorMessage();
   auto& res = *resources;
   ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
-  ASSERT_RESULT(MappingExists(res, 0x7f010000, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                              true /* rewrite */));  // integer/int1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000c, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020000,
-                              true /* rewrite */));  // string/str1
-  ASSERT_RESULT(MappingExists(res, 0x7f02000e, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020001,
-                              true /* rewrite */));  // string/str3
-  ASSERT_RESULT(MappingExists(res, 0x7f02000f, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f020002,
-                              true /* rewrite */));  // string/str4
+  ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000,
+                              false /* rewrite */));  // integer/int1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000,
+                              false /* rewrite */));  // string/str1
+  ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001,
+                              false /* rewrite */));  // string/str3
+  ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002,
+                              false /* rewrite */));  // string/str4
 }
 
 // Overlays that are neither pre-installed nor signed with the same signature as the target cannot
@@ -291,24 +292,24 @@
     ASSERT_TRUE(resources) << resources.GetErrorMessage();
     auto& res = *resources;
     ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 9U);
-    ASSERT_RESULT(MappingExists(res, 0x7f020003, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010000,
-                                true /* rewrite */));  // string/not_overlayable
-    ASSERT_RESULT(MappingExists(res, 0x7f020004, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010001,
-                                true /* rewrite */));  // string/other
-    ASSERT_RESULT(MappingExists(res, 0x7f020005, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010002,
-                                true /* rewrite */));  // string/policy_odm
-    ASSERT_RESULT(MappingExists(res, 0x7f020006, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010003,
-                                true /* rewrite */));  // string/policy_oem
-    ASSERT_RESULT(MappingExists(res, 0x7f020007, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010004,
-                                true /* rewrite */));  // string/policy_product
-    ASSERT_RESULT(MappingExists(res, 0x7f020008, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010005,
-                                true /* rewrite */));  // string/policy_public
-    ASSERT_RESULT(MappingExists(res, 0x7f020009, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010006,
-                                true /* rewrite */));  // string/policy_signature
-    ASSERT_RESULT(MappingExists(res, 0x7f02000a, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010007,
-                                true /* rewrite */));  // string/policy_system
-    ASSERT_RESULT(MappingExists(res, 0x7f02000b, 0x01 /* Res_value::TYPE_REFERENCE */, 0x7f010008,
-                                true /* rewrite */));  // string/policy_system_vendor
+    ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
+                                false /* rewrite */));  // string/not_overlayable
+    ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
+                                false /* rewrite */));  // string/other
+    ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
+                                false /* rewrite */));  // string/policy_odm
+    ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
+                                false /* rewrite */));  // string/policy_oem
+    ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
+                                false /* rewrite */));  // string/policy_product
+    ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
+                                false /* rewrite */));  // string/policy_public
+    ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
+                                false /* rewrite */));  // string/policy_signature
+    ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
+                                false /* rewrite */));  // string/policy_system
+    ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
+                                false /* rewrite */));  // string/policy_system_vendor
   };
 
   CheckEntries(PolicyFlags::POLICY_SIGNATURE);
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index a7c2f28..8868b53 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -30,7 +30,7 @@
     0x49, 0x44, 0x4d, 0x50,
 
     // 0x4: version
-    0x01, 0x00, 0x00, 0x00,
+    0x02, 0x00, 0x00, 0x00,
 
     // 0x8: target crc
     0x34, 0x12, 0x00, 0x00,
@@ -38,8 +38,8 @@
     // 0xc: overlay crc
     0x78, 0x56, 0x00, 0x00,
 
-    // 0x10: target path "target.apk"
-    0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    // 0x10: target path "targetX.apk"
+    0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -56,8 +56,8 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
-    // 0x110: overlay path "overlay.apk"
-    0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
+    // 0x110: overlay path "overlayX.apk"
+    0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -75,49 +75,63 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
     // DATA HEADER
-    // 0x210: target package id
-    0x7f, 0x00,
+    // 0x210: target_package_id
+    0x7f,
 
-    // 0x212: types count
-    0x02, 0x00,
+    // 0x211: overlay_package_id
+    0x7f,
 
-    // DATA BLOCK
-    // 0x214: target type
-    0x02, 0x00,
+    // 0x212: target_entry_count
+    0x03, 0x00, 0x00, 0x00,
 
-    // 0x216: overlay type
-    0x02, 0x00,
+    // 0x216: overlay_entry_count
+    0x03, 0x00, 0x00, 0x00,
 
-    // 0x218: entry count
-    0x01, 0x00,
-
-    // 0x21a: entry offset
-    0x00, 0x00,
-
-    // 0x21c: entries
+    // 0x21a: string_pool_offset
     0x00, 0x00, 0x00, 0x00,
 
-    // DATA BLOCK
-    // 0x220: target type
-    0x03, 0x00,
-
-    // 0x222: overlay type
-    0x03, 0x00,
-
-    // 0x224: entry count
-    0x03, 0x00,
-
-    // 0x226: entry offset
-    0x03, 0x00,
-
-    // 0x228, 0x22c, 0x230: entries
+    // 0x21e: string_pool_byte_length
     0x00, 0x00, 0x00, 0x00,
 
-    0xff, 0xff, 0xff, 0xff,
+    // TARGET ENTRIES
+    // 0x222: 0x7f020000
+    0x00, 0x00, 0x02, 0x7f,
 
-    0x01, 0x00, 0x00, 0x00};
+    // 0x226: TYPE_REFERENCE
+    0x01,
 
-const unsigned int idmap_raw_data_len = 565;
+    // 0x227: 0x7f020000
+    0x00, 0x00, 0x02, 0x7f,
+
+    // 0x22b: 0x7f030000
+    0x00, 0x00, 0x03, 0x7f,
+
+    // 0x22f: TYPE_REFERENCE
+    0x01,
+
+    // 0x230: 0x7f030000
+    0x00, 0x00, 0x03, 0x7f,
+
+    // 0x234: 0x7f030002
+    0x02, 0x00, 0x03, 0x7f,
+
+    // 0x238: TYPE_REFERENCE
+    0x01,
+
+    // 0x239: 0x7f030001
+    0x01, 0x00, 0x03, 0x7f,
+
+    // OVERLAY ENTRIES
+    // 0x23d: 0x7f020000 -> 0x7f020000
+    0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
+
+    // 0x245: 0x7f030000 -> 0x7f030000
+    0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
+
+    // 0x24d: 0x7f030001 -> 0x7f030002
+    0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f};
+
+const unsigned int idmap_raw_data_len = 0x255;
 
 std::string GetTestDataPath();
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 6249de3..8618d4d 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5760,6 +5760,8 @@
         AUTO_DENIED = 8;
         // permission request was ignored because permission is restricted
         IGNORED_RESTRICTED_PERMISSION = 9;
+        // one time permission was granted by user action
+        USER_GRANTED_ONE_TIME = 10;
     }
     // The result of the permission grant
     optional Result result = 6;
diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp
index 92200f9..b59d88d 100755
--- a/cmds/statsd/src/socket/StatsSocketListener.cpp
+++ b/cmds/statsd/src/socket/StatsSocketListener.cpp
@@ -56,8 +56,7 @@
     }
 
     // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
-    char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) + LOGGER_ENTRY_MAX_PAYLOAD +
-                1];
+    char buffer[sizeof(android_log_header_t) + LOGGER_ENTRY_MAX_PAYLOAD + 1];
     struct iovec iov = {buffer, sizeof(buffer) - 1};
 
     alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index c98b2cf..0664867 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -35,7 +35,7 @@
 
 enum TimeUnit {
   TIME_UNIT_UNSPECIFIED = 0;
-  ONE_MINUTE = 1;
+  ONE_MINUTE = 1;  // WILL BE GUARDRAILED TO 5 MINS UNLESS UID = SHELL OR ROOT
   FIVE_MINUTES = 2;
   TEN_MINUTES = 3;
   THIRTY_MINUTES = 4;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 4603f08..47fdcde 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -850,6 +850,7 @@
         GestureResultCallbackInfo callbackInfo;
         synchronized (mLock) {
             callbackInfo = mGestureStatusCallbackInfos.get(sequence);
+            mGestureStatusCallbackInfos.remove(sequence);
         }
         final GestureResultCallbackInfo finalCallbackInfo = callbackInfo;
         if ((callbackInfo != null) && (callbackInfo.gestureDescription != null)
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index cf24b8e..e738b19 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
 
+import android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.UnsupportedAppUsage;
@@ -322,6 +323,14 @@
      */
     public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 0x00000400;
 
+    /**
+     * This flag indicates that the accessibility service will handle the shortcut action itself.
+     * A callback {@link AccessibilityButtonCallback#onClicked(AccessibilityButtonController)} is
+     * called when the user presses the accessibility shortcut. Otherwise, the service is enabled
+     * or disabled by the system instead.
+     */
+    public static final int FLAG_HANDLE_SHORTCUT = 0x00000800;
+
     /** {@hide} */
     public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
 
@@ -423,12 +432,13 @@
      * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
      * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
      * @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
+     * @see #FLAG_HANDLE_SHORTCUT
      */
     public int flags;
 
     /**
      * Whether or not the service has crashed and is awaiting restart. Only valid from {@link
-     * android.view.accessibility.AccessibilityManager#getEnabledAccessibilityServiceList(int)},
+     * android.view.accessibility.AccessibilityManager#getInstalledAccessibilityServiceList()},
      * because that is populated from the internal list of running services.
      *
      * @hide
@@ -1103,6 +1113,8 @@
                 return "FLAG_REQUEST_FINGERPRINT_GESTURES";
             case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
                 return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
+            case FLAG_HANDLE_SHORTCUT:
+                return "FLAG_HANDLE_SHORTCUT";
             default:
                 return null;
         }
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 26c2c0c..f4e465a 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -563,6 +563,21 @@
      * account, or the AbstractAcccountAuthenticator managing the account did so or because the
      * client shares a signature with the managing AbstractAccountAuthenticator.
      *
+     * <div class="caution"><p><b>Caution: </b>This method returns personal and sensitive user data.
+     * If your app accesses, collects, uses, or shares personal and sensitive data, you must clearly
+     * disclose that fact to users. For apps published on Google Play, policies protecting user data
+     * require that you do the following:</p>
+     * <ul>
+     * <li>Disclose to the user how your app accesses, collects, uses, or shares personal and
+     * sensitive data. Learn more about
+     * <a href="https://play.google.com/about/privacy-security-deception/user-data/#!#personal-sensitive">acceptable
+     * disclosure and consent</a>.</li>
+     * <li>Provide a privacy policy that describes your use of this data on- and off-device.</li>
+     * </ul>
+     * <p>To learn more, visit the
+     * <a href="https://play.google.com/about/privacy-security-deception/user-data">Google Play
+     * Policy regarding user data</a>.</p></div>
+     *
      * <p>
      * It is safe to call this method from the main thread.
      *
@@ -649,6 +664,22 @@
      * the account. For example, there are types corresponding to Google and Facebook. The exact
      * string token to use will be published somewhere associated with the authenticator in
      * question.
+     * </p>
+     *
+     * <div class="caution"><p><b>Caution: </b>This method returns personal and sensitive user data.
+     * If your app accesses, collects, uses, or shares personal and sensitive data, you must clearly
+     * disclose that fact to users. For apps published on Google Play, policies protecting user data
+     * require that you do the following:</p>
+     * <ul>
+     * <li>Disclose to the user how your app accesses, collects, uses, or shares personal and
+     * sensitive data. Learn more about
+     * <a href="https://play.google.com/about/privacy-security-deception/user-data/#!#personal-sensitive">acceptable
+     * disclosure and consent</a>.</li>
+     * <li>Provide a privacy policy that describes your use of this data on- and off-device.</li>
+     * </ul>
+     * <p>To learn more, visit the
+     * <a href="https://play.google.com/about/privacy-security-deception/user-data">Google Play
+     * Policy regarding user data</a>.</p></div>
      *
      * <p>
      * It is safe to call this method from the main thread.
diff --git a/core/java/android/annotation/UnsupportedAppUsage.java b/core/java/android/annotation/UnsupportedAppUsage.java
index a454df5..204d71d 100644
--- a/core/java/android/annotation/UnsupportedAppUsage.java
+++ b/core/java/android/annotation/UnsupportedAppUsage.java
@@ -83,8 +83,9 @@
      * <p>Possible values are:
      * <ul>
      *     <li>
-     *         {@link android.os.Build.VERSION_CODES#O} or {@link android.os.Build.VERSION_CODES#P},
-     *         to limit access to apps targeting these SDKs (or earlier).
+     *         An API level like {@link android.os.Build.VERSION_CODES#O} - in which case the API is
+     *         available up to and including the specified release. Or, in other words, the API is
+     *         blacklisted (unavailable) from the next API level from the one specified.
      *     </li>
      *     <li>
      *         absent (default value) - All apps can access this API, but doing so may result in
@@ -94,10 +95,6 @@
      *
      * </ul>
      *
-     * Note, if this is set to {@link android.os.Build.VERSION_CODES#O}, apps targeting O
-     * maintenance releases will also be allowed to use the API, and similarly for any future
-     * maintenance releases of P.
-     *
      * @return The maximum value for an apps targetSdkVersion in order to access this API.
      */
     int maxTargetSdk() default Integer.MAX_VALUE;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 03300e4..9872e30 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2563,9 +2563,12 @@
     }
 
     /**
-     * Report to the system that your app is now fully drawn, purely for diagnostic
-     * purposes (calling it does not impact the visible behavior of the activity).
-     * This is only used to help instrument application launch times, so that the
+     * Report to the system that your app is now fully drawn, for diagnostic and
+     * optimization purposes.  The system may adjust optimizations to prioritize
+     * work that happens before reportFullyDrawn is called, to improve app startup.
+     * Misrepresenting the startup window by calling reportFullyDrawn too late or too
+     * early may decrease application and startup performance.<p>
+     * This is also used to help instrument application launch times, so that the
      * app can report when it is fully in a usable state; without this, the only thing
      * the system itself can determine is the point at which the activity's window
      * is <em>first</em> drawn and displayed.  To participate in app launch time
@@ -7097,14 +7100,28 @@
     }
 
     /**
-     * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a
-     * fullscreen opaque Activity.
+     * Convert an activity, which particularly with {@link android.R.attr#windowIsTranslucent} or
+     * {@link android.R.attr#windowIsFloating} attribute, to a fullscreen opaque activity, or
+     * convert it from opaque back to translucent.
+     *
+     * @param translucent {@code true} convert from opaque to translucent.
+     *                    {@code false} convert from translucent to opaque.
+     * @return The result of setting translucency. Return {@code true} if set successfully,
+     *         {@code false} otherwise.
+     */
+    public boolean setTranslucent(boolean translucent) {
+        if (translucent) {
+            return convertToTranslucent(null /* callback */, null /* options */);
+        } else {
+            return convertFromTranslucentInternal();
+        }
+    }
+
+    /**
+     * Convert an activity to a fullscreen opaque activity.
      * <p>
-     * Call this whenever the background of a translucent Activity has changed to become opaque.
-     * Doing so will allow the {@link android.view.Surface} of the Activity behind to be released.
-     * <p>
-     * This call has no effect on non-translucent activities or on activities with the
-     * {@link android.R.attr#windowIsFloating} attribute.
+     * Call this whenever the background of a translucent activity has changed to become opaque.
+     * Doing so will allow the {@link android.view.Surface} of the activity behind to be released.
      *
      * @see #convertToTranslucent(android.app.Activity.TranslucentConversionListener,
      * ActivityOptions)
@@ -7114,31 +7131,33 @@
      */
     @SystemApi
     public void convertFromTranslucent() {
+        convertFromTranslucentInternal();
+    }
+
+    private boolean convertFromTranslucentInternal() {
         try {
             mTranslucentCallback = null;
             if (ActivityTaskManager.getService().convertFromTranslucent(mToken)) {
                 WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, true);
+                return true;
             }
         } catch (RemoteException e) {
             // pass
         }
+        return false;
     }
 
     /**
-     * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} back from
-     * opaque to translucent following a call to {@link #convertFromTranslucent()}.
+     * Convert an activity to a translucent activity.
      * <p>
-     * Calling this allows the Activity behind this one to be seen again. Once all such Activities
+     * Calling this allows the activity behind this one to be seen again. Once all such activities
      * have been redrawn {@link TranslucentConversionListener#onTranslucentConversionComplete} will
      * be called indicating that it is safe to make this activity translucent again. Until
      * {@link TranslucentConversionListener#onTranslucentConversionComplete} is called the image
-     * behind the frontmost Activity will be indeterminate.
-     * <p>
-     * This call has no effect on non-translucent activities or on activities with the
-     * {@link android.R.attr#windowIsFloating} attribute.
+     * behind the frontmost activity will be indeterminate.
      *
-     * @param callback the method to call when all visible Activities behind this one have been
-     * drawn and it is safe to make this Activity translucent again.
+     * @param callback the method to call when all visible activities behind this one have been
+     * drawn and it is safe to make this activity translucent again.
      * @param options activity options delivered to the activity below this one. The options
      * are retrieved using {@link #getActivityOptions}.
      * @return <code>true</code> if Window was opaque and will become translucent or
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 0f9a6e6..5c4125e 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -204,14 +204,7 @@
         }
         mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity,
                 resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning(),
-                mEnterActivityOptions.isCrossTask(),
-                () -> {
-                    if (isReturning) {
-                        // once it is done transitioning, we don't need the coordinator --
-                        // if we kept it around, it could leak Views
-                        mEnterTransitionCoordinator = null;
-                    }
-                });
+                mEnterActivityOptions.isCrossTask());
         if (mEnterActivityOptions.isCrossTask()) {
             mExitingFrom = new ArrayList<>(mEnterActivityOptions.getSharedElementNames());
             mExitingTo = new ArrayList<>(mEnterActivityOptions.getSharedElementNames());
@@ -280,6 +273,10 @@
                             mEnterTransitionCoordinator.isWaitingForRemoteExit()) {
                         restoreExitedViews();
                         restoreReenteringViews();
+                    } else if (mEnterTransitionCoordinator.isReturning()) {
+                        mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> {
+                            mEnterTransitionCoordinator = null;
+                        });
                     }
                 }
             }, 1000);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1649e8b..8bca87e6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -50,6 +50,7 @@
 import android.util.ArrayMap;
 import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -77,10 +78,12 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
+import java.util.function.ToLongFunction;
 
 /**
  * API for interacting with "application operation" tracking.
@@ -2052,7 +2055,7 @@
      *
      * @see #markAppOpNoted
      */
-    private static final ThreadLocal<long[]> sAppOpsNotedInThisBinderTransaction =
+    private static final ThreadLocal<ArrayMap<String, long[]>> sAppOpsNotedInThisBinderTransaction =
             new ThreadLocal<>();
 
     /** Whether noting for an appop should be collected */
@@ -2329,51 +2332,42 @@
     }
 
     /**
-     * Class holding the information about one unique operation of an application.
+     * Class holding the information about one unique operation of a
+     * {@link Context#createFeatureContext(String) feature}.
+     *
      * @hide
      */
     @TestApi
     @Immutable
     @SystemApi
-    public static final class OpEntry implements Parcelable {
-        private final int mOp;
+    public static final class OpFeatureEntry {
+        private final @NonNull OpEntry mParent;
         private final boolean mRunning;
-        private final @Mode int mMode;
+
         private final @Nullable LongSparseLongArray mAccessTimes;
         private final @Nullable LongSparseLongArray mRejectTimes;
         private final @Nullable LongSparseLongArray mDurations;
         private final @Nullable LongSparseLongArray mProxyUids;
         private final @Nullable LongSparseArray<String> mProxyPackageNames;
+        private final @Nullable LongSparseArray<String> mProxyFeatureIds;
 
         /**
          * @hide
          */
-        public OpEntry(int op, boolean running, @Mode int mode,
-                @Nullable LongSparseLongArray accessTimes, @Nullable LongSparseLongArray rejectTimes,
+        public OpFeatureEntry(@NonNull OpEntry parent, boolean running,
+                @Nullable LongSparseLongArray accessTimes,
+                @Nullable LongSparseLongArray rejectTimes,
                 @Nullable LongSparseLongArray durations, @Nullable LongSparseLongArray proxyUids,
-                @Nullable LongSparseArray<String> proxyPackageNames) {
-            mOp = op;
+                @Nullable LongSparseArray<String> proxyPackageNames,
+                @Nullable LongSparseArray<String> proxyFeatureIds) {
+            mParent = Preconditions.checkNotNull(parent);
             mRunning = running;
-            mMode = mode;
             mAccessTimes = accessTimes;
             mRejectTimes = rejectTimes;
             mDurations = durations;
             mProxyUids = proxyUids;
             mProxyPackageNames = proxyPackageNames;
-        }
-
-        /**
-         * @hide
-         */
-        public OpEntry(int op, @Mode int mode) {
-            mOp = op;
-            mMode = mode;
-            mRunning = false;
-            mAccessTimes = null;
-            mRejectTimes = null;
-            mDurations = null;
-            mProxyUids = null;
-            mProxyPackageNames = null;
+            mProxyFeatureIds = proxyFeatureIds;
         }
 
         /**
@@ -2390,29 +2384,6 @@
         /**
          * @hide
          */
-        @UnsupportedAppUsage
-        public int getOp() {
-            return mOp;
-        }
-
-        /**
-         * @return This entry's op string name, such as {@link #OPSTR_COARSE_LOCATION}.
-         */
-        public @NonNull String getOpStr() {
-            return sOpToString[mOp];
-        }
-
-        /**
-         * @return this entry's current mode, such as {@link #MODE_ALLOWED}.
-         */
-        public @Mode int getMode() {
-            return mMode;
-        }
-
-        /**
-         * @hide
-         */
-        @UnsupportedAppUsage
         public long getTime() {
             return getLastAccessTime(OP_FLAGS_ALL);
         }
@@ -2455,7 +2426,7 @@
          */
         public long getLastAccessForegroundTime(@OpFlags int flags) {
             return maxForFlagsInStates(mAccessTimes, MAX_PRIORITY_UID_STATE,
-                    resolveFirstUnrestrictedUidState(mOp), flags);
+                    resolveFirstUnrestrictedUidState(mParent.mOp), flags);
         }
 
         /**
@@ -2475,7 +2446,7 @@
          * @see #getLastAccessTime(int, int, int)
          */
         public long getLastAccessBackgroundTime(@OpFlags int flags) {
-            return maxForFlagsInStates(mAccessTimes, resolveLastRestrictedUidState(mOp),
+            return maxForFlagsInStates(mAccessTimes, resolveLastRestrictedUidState(mParent.mOp),
                     MIN_PRIORITY_UID_STATE, flags);
         }
 
@@ -2509,7 +2480,6 @@
         /**
          * @hide
          */
-        @UnsupportedAppUsage
         public long getRejectTime() {
             return getLastRejectTime(OP_FLAGS_ALL);
         }
@@ -2553,7 +2523,7 @@
          */
         public long getLastRejectForegroundTime(@OpFlags int flags) {
             return maxForFlagsInStates(mRejectTimes, MAX_PRIORITY_UID_STATE,
-                    resolveFirstUnrestrictedUidState(mOp), flags);
+                    resolveFirstUnrestrictedUidState(mParent.mOp), flags);
         }
 
         /**
@@ -2573,7 +2543,7 @@
          * @see #getLastRejectTime(int)
          */
         public long getLastRejectBackgroundTime(@OpFlags int flags) {
-            return maxForFlagsInStates(mRejectTimes, resolveLastRestrictedUidState(mOp),
+            return maxForFlagsInStates(mRejectTimes, resolveLastRestrictedUidState(mParent.mOp),
                     MIN_PRIORITY_UID_STATE, flags);
         }
 
@@ -2633,7 +2603,7 @@
          */
         public long getLastForegroundDuration(@OpFlags int flags) {
             return sumForFlagsInStates(mDurations, MAX_PRIORITY_UID_STATE,
-                    resolveFirstUnrestrictedUidState(mOp), flags);
+                    resolveFirstUnrestrictedUidState(mParent.mOp), flags);
         }
 
         /**
@@ -2651,7 +2621,7 @@
          * @see #getLastDuration(int, int, int)
          */
         public long getLastBackgroundDuration(@OpFlags int flags) {
-            return sumForFlagsInStates(mDurations, resolveLastRestrictedUidState(mOp),
+            return sumForFlagsInStates(mDurations, resolveLastRestrictedUidState(mParent.mOp),
                     MIN_PRIORITY_UID_STATE, flags);
         }
 
@@ -2736,12 +2706,663 @@
          * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
          * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
          * for any flag.
-         * @return The proxy package name.
+         * @return The feature id.
          */
         public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
             return findFirstNonNullForFlagsInStates(mProxyPackageNames, uidState, uidState, flags);
         }
 
+        /**
+         * Gets the feature of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app or {@code null}
+         * if there is no proxy.
+         *
+         * @return The proxy package name.
+         */
+        public @Nullable String getProxyFeatureId() {
+            return findFirstNonNullForFlagsInStates(mProxyFeatureIds, MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Gets the feature of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app for a UID state or
+         * {@code null} if there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return The feature id.
+         */
+        public @Nullable String getProxyFeatureId(@UidState int uidState, @OpFlags int flags) {
+            return findFirstNonNullForFlagsInStates(mProxyFeatureIds, uidState, uidState, flags);
+        }
+
+        /**
+         * @hide
+         */
+        public static class Builder {
+            private final boolean mRunning;
+
+            private final @Nullable LongSparseLongArray mAccessTimes;
+            private final @Nullable LongSparseLongArray mRejectTimes;
+            private final @Nullable LongSparseLongArray mDurations;
+            private final @Nullable LongSparseLongArray mProxyUids;
+            private final @Nullable LongSparseArray<String> mProxyPackageNames;
+            private final @Nullable LongSparseArray<String> mProxyFeatureIds;
+            private @NonNull OpEntry mParent;
+
+            public Builder(boolean running, @Nullable LongSparseLongArray accessTimes,
+                    @Nullable LongSparseLongArray rejectTimes,
+                    @Nullable LongSparseLongArray durations,
+                    @Nullable LongSparseLongArray proxyUids,
+                    @Nullable LongSparseArray<String> proxyPackageNames,
+                    @Nullable LongSparseArray<String> proxyFeatureIds) {
+                mRunning = running;
+                mAccessTimes = accessTimes;
+                mRejectTimes = rejectTimes;
+                mDurations = durations;
+                mProxyUids = proxyUids;
+                mProxyPackageNames = proxyPackageNames;
+                mProxyFeatureIds = proxyFeatureIds;
+            }
+
+            public Builder setParent(@NonNull OpEntry parent) {
+                mParent = parent;
+
+                return this;
+            }
+
+            /**
+             * Create OpFeatureEntry from builder
+             */
+            public OpFeatureEntry build() {
+                Preconditions.checkNotNull(mParent);
+
+                return new OpFeatureEntry(mParent, mRunning, mAccessTimes, mRejectTimes,
+                        mDurations, mProxyUids, mProxyPackageNames, mProxyFeatureIds);
+            }
+        }
+
+        /**
+         * @hide
+         */
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            LongSparseLongArray.Parcelling longSparseLongArrayParcelling =
+                    LongSparseLongArray.Parcelling.Cache.getOrCreate(
+                            LongSparseLongArray.Parcelling.class);
+            LongSparseArray.StringParcelling longSparseStringArrayParcelling =
+                    LongSparseArray.StringParcelling.Cache.getOrCreate(
+                            LongSparseArray.StringParcelling.class);
+
+            dest.writeBoolean(mRunning);
+            longSparseLongArrayParcelling.parcel(mAccessTimes, dest, flags);
+            longSparseLongArrayParcelling.parcel(mRejectTimes, dest, flags);
+            longSparseLongArrayParcelling.parcel(mDurations, dest, flags);
+            longSparseLongArrayParcelling.parcel(mProxyUids, dest, flags);
+            longSparseStringArrayParcelling.parcel(mProxyPackageNames, dest, flags);
+            longSparseStringArrayParcelling.parcel(mProxyFeatureIds, dest, flags);
+        }
+
+        /**
+         * @hide
+         */
+        public static OpFeatureEntry.Builder createFromParcel(@NonNull Parcel source) {
+            LongSparseLongArray.Parcelling longSparseLongArrayParcelling =
+                    LongSparseLongArray.Parcelling.Cache.getOrCreate(
+                            LongSparseLongArray.Parcelling.class);
+            LongSparseArray.StringParcelling longSparseStringArrayParcelling =
+                    LongSparseArray.StringParcelling.Cache.getOrCreate(
+                            LongSparseArray.StringParcelling.class);
+
+            return new OpFeatureEntry.Builder(source.readBoolean(),
+                    longSparseLongArrayParcelling.unparcel(source),
+                    longSparseLongArrayParcelling.unparcel(source),
+                    longSparseLongArrayParcelling.unparcel(source),
+                    longSparseLongArrayParcelling.unparcel(source),
+                    longSparseStringArrayParcelling.unparcel(source),
+                    longSparseStringArrayParcelling.unparcel(source));
+        }
+    }
+
+    /**
+     * Class holding the information about one unique operation of an application.
+     * @hide
+     */
+    @TestApi
+    @Immutable
+    @SystemApi
+    public static final class OpEntry implements Parcelable {
+        private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp;
+        private final @Mode int mMode;
+        private final @NonNull ArrayMap<String, OpFeatureEntry> mFeatures;
+
+        /**
+         * @hide
+         */
+        public OpEntry(@IntRange(from = 0, to = _NUM_OP - 1) int op, @Mode int mode,
+                @NonNull Pair<String, OpFeatureEntry.Builder>[] featureBuilders) {
+            mOp = Preconditions.checkArgumentInRange(op, 0, _NUM_OP - 1, "op");
+            mMode = Preconditions.checkArgumentInRange(mode, 0, MODE_FOREGROUND, "mode");
+
+            mFeatures = new ArrayMap<>(featureBuilders.length);
+            for (Pair<String, OpFeatureEntry.Builder> feature : featureBuilders) {
+                mFeatures.put(feature.first, feature.second.setParent(this).build());
+            }
+        }
+
+        /**
+         * @return The mapping from the feature ids to the feature state
+         */
+        public @NonNull Map<String, OpFeatureEntry> getFeatures() {
+            return mFeatures;
+        }
+
+        /**
+         * @hide
+         */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+                + "#getOpStr()}")
+        public int getOp() {
+            return mOp;
+        }
+
+        /**
+         * @return This entry's op string name, such as {@link #OPSTR_COARSE_LOCATION}.
+         */
+        public @NonNull String getOpStr() {
+            return sOpToString[mOp];
+        }
+
+        /**
+         * @return this entry's current mode, such as {@link #MODE_ALLOWED}.
+         */
+        public @Mode int getMode() {
+            return mMode;
+        }
+
+        /**
+         * @deprecated Use {@link OpEntry#getLastAccessTime(int)} instead
+         *
+         * @hide
+         */
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+                + "#getLastAccessTime(int)}")
+        public long getTime() {
+            return getLastAccessTime(OP_FLAGS_ALL);
+        }
+
+        private long getMaxOfFeatures(@NonNull ToLongFunction<OpFeatureEntry> timeGetter) {
+            long max = 0;
+
+            int numFeatures = mFeatures.size();
+            for (int i = 0; i < numFeatures; i++) {
+                max = Math.max(max, timeGetter.applyAsLong(mFeatures.valueAt(i)));
+            }
+
+            return max;
+        }
+
+        private long getSumOfFeatures(@NonNull ToLongFunction<OpFeatureEntry> getter) {
+            long sum = 0;
+
+            int numFeatures = mFeatures.size();
+            for (int i = 0; i < numFeatures; i++) {
+                sum += getter.applyAsLong(mFeatures.valueAt(i));
+            }
+
+            return sum;
+        }
+
+        /**
+         * Return the last wall clock time  in milliseconds this op was accessed
+         * by the app for a given range of UID states.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
+         */
+        public long getLastAccessTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds this op was accessed
+         * by the app while in the foreground.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
+         * @see #getLastAccessTime(int, int, int)
+         */
+        public long getLastAccessForegroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessForegroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds this op was accessed
+         * by the app while in the background.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessTime(int)
+         * @see #getLastAccessTime(int, int, int)
+         */
+        public long getLastAccessBackgroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessBackgroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time  in milliseconds this op was accessed
+         * by the app for a given range of UID states.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
+         */
+        public long getLastAccessTime(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastAccessTime(fromUidState,
+                            toUidState, flags)));
+        }
+
+        /**
+         * @deprecated Use {@link OpEntry#getLastRejectTime(int)} instead
+         *
+         * @hide
+         */
+        @Deprecated
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "{@code "
+                + "#getLastRejectTime(int)}")
+        public long getRejectTime() {
+            return getLastRejectTime(OP_FLAGS_ALL);
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         */
+        public long getLastRejectTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op while in the foreground but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         * @see #getLastRejectTime(int)
+         */
+        public long getLastRejectForegroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectForegroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op while in the background but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last background reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         * @see #getLastRejectTime(int)
+         */
+        public long getLastRejectBackgroundTime(@OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectBackgroundTime(flags)));
+        }
+
+        /**
+         * Return the last wall clock time state in milliseconds the app made an
+         * attempt to access this op for a given range of UID states.
+         *
+         * @param fromUidState The UID state from which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state to which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectTime(int)
+         */
+        public long getLastRejectTime(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return getMaxOfFeatures(
+                    (featureEntry -> featureEntry.getLastRejectTime(fromUidState,
+                            toUidState, flags)));
+        }
+
+        /**
+         * @return Whether the operation is running.
+         */
+        public boolean isRunning() {
+            int numFeatures = mFeatures.size();
+            if (mFeatures.isEmpty()) {
+                return false;
+            }
+
+            for (int i = 0; i < numFeatures; i++) {
+                if (mFeatures.valueAt(i).mRunning) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * @return The duration of the operation in milliseconds. The duration is in wall time.
+         */
+        public long getDuration() {
+            return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op while
+         * in the foreground. The duration is in wall time.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the foreground access duration in milliseconds.
+         *
+         * @see #getLastBackgroundDuration(int)
+         * @see #getLastDuration(int, int, int)
+         */
+        public long getLastForegroundDuration(@OpFlags int flags) {
+            return getSumOfFeatures((featureEntry) ->
+                    featureEntry.getLastForegroundDuration(flags));
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op while
+         * in the background. The duration is in wall time.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the background access duration in milliseconds.
+         *
+         * @see #getLastForegroundDuration(int)
+         * @see #getLastDuration(int, int, int)
+         */
+        public long getLastBackgroundDuration(@OpFlags int flags) {
+            return getSumOfFeatures((featureEntry) ->
+                    featureEntry.getLastBackgroundDuration(flags));
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op for
+         * a given range of UID states. The duration is in wall time.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the access duration in milliseconds.
+         */
+        public long getLastDuration(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return getSumOfFeatures((featureEntry) ->
+                    featureEntry.getLastDuration(fromUidState, toUidState, flags));
+        }
+
+        /**
+         * Like {@link #findFirstNonNegativeForFlagsInStates(LongSparseLongArray, int, int, int)}
+         * but for all proxy uid in all features.
+         */
+        private long findFirstNonNegativeProxyUidInFeatureStates(@UidState int beginUidState,
+                @UidState int endUidState, @OpFlags int flags) {
+            int numFeatures = mFeatures.size();
+
+            if (numFeatures == 0) {
+                return -1;
+            }
+
+            while (flags != 0) {
+                final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+                flags &= ~flag;
+                for (int uidState : UID_STATES) {
+                    if (uidState < beginUidState || uidState > endUidState) {
+                        continue;
+                    }
+
+                    final long key = makeKey(uidState, flag);
+
+                    for (int i = 0; i < numFeatures; i++) {
+                        OpFeatureEntry featureEntry = mFeatures.valueAt(i);
+
+                        if (featureEntry.mProxyUids == null) {
+                            continue;
+                        }
+
+                        final long proxyUid = featureEntry.mProxyUids.get(key);
+                        if (proxyUid >= 0) {
+                            return proxyUid;
+                        }
+                    }
+                }
+            }
+
+            return -1;
+        }
+
+        /**
+         * Like {@link #findFirstNonNullForFlagsInStates(LongSparseArray, int, int, int)} but
+         * for all proxyPackageNames in all features.
+         */
+        private @Nullable String findFirstNonNullProxyPackageNameInFeatureStates(
+                @OpFlags int flags, @UidState int beginUidState, @UidState int endUidState) {
+            int numFeatures = mFeatures.size();
+
+            if (numFeatures == 0) {
+                return null;
+            }
+
+            while (flags != 0) {
+                final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+                flags &= ~flag;
+                for (int uidState : UID_STATES) {
+                    if (uidState < beginUidState || uidState > endUidState) {
+                        continue;
+                    }
+                    final long key = makeKey(uidState, flag);
+
+                    for (int i = 0; i < numFeatures; i++) {
+                        OpFeatureEntry featureEntry = mFeatures.valueAt(i);
+
+                        if (featureEntry.mProxyPackageNames == null) {
+                            continue;
+                        }
+
+                        final String proxyName = featureEntry.mProxyPackageNames.get(key);
+                        if (proxyName != null) {
+                            return proxyName;
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
+         * @deprecated Use {@link #getProxyUid(int, int)} instead
+         */
+        @Deprecated
+        public int getProxyUid() {
+            return (int) findFirstNonNegativeProxyUidInFeatureStates(MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Gets the UID of the app that performed the op on behalf of this app and
+         * as a result blamed the op on this app or {@link Process#INVALID_UID} if
+         * there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return The proxy UID.
+         */
+        public int getProxyUid(@UidState int uidState, @OpFlags int flags) {
+            return (int) findFirstNonNegativeProxyUidInFeatureStates(uidState, uidState, flags);
+        }
+
+        /**
+         * @deprecated Use {@link #getProxyPackageName(int, int)} instead
+         */
+        @Deprecated
+        public @Nullable String getProxyPackageName() {
+            return findFirstNonNullProxyPackageNameInFeatureStates(MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Gets the package name of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app for a UID state or
+         * {@code null} if there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return The proxy package name.
+         */
+        public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
+            return findFirstNonNullProxyPackageNameInFeatureStates(uidState, uidState, flags);
+        }
+
+        /**
+         * Create OpEntry from parcel.
+         *
+         * @hide
+         */
+        public static OpEntry createFromParcel(@NonNull Parcel source) {
+            int op = source.readInt();
+            int mode = source.readInt();
+
+            int numFeatures = source.readInt();
+            Pair<String, OpFeatureEntry.Builder>[] features = new Pair[numFeatures];
+            for (int i = 0; i < numFeatures; i++) {
+                features[i] = new Pair<>(source.readString(),
+                        OpFeatureEntry.createFromParcel(source));
+            }
+
+            return new OpEntry(op, mode, features);
+        }
+
         @Override
         public int describeContents() {
             return 0;
@@ -2751,31 +3372,23 @@
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mOp);
             dest.writeInt(mMode);
-            dest.writeBoolean(mRunning);
-            writeLongSparseLongArrayToParcel(mAccessTimes, dest);
-            writeLongSparseLongArrayToParcel(mRejectTimes, dest);
-            writeLongSparseLongArrayToParcel(mDurations, dest);
-            writeLongSparseLongArrayToParcel(mProxyUids, dest);
-            writeLongSparseStringArrayToParcel(mProxyPackageNames, dest);
+
+            int numFeatures = mFeatures.size();
+            dest.writeInt(numFeatures);
+            for (int i = 0; i < numFeatures; i++) {
+                dest.writeString(mFeatures.keyAt(i));
+                mFeatures.valueAt(i).writeToParcel(dest, flags);
+            }
         }
 
-        OpEntry(Parcel source) {
-            mOp = source.readInt();
-            mMode = source.readInt();
-            mRunning = source.readBoolean();
-            mAccessTimes = readLongSparseLongArrayFromParcel(source);
-            mRejectTimes = readLongSparseLongArrayFromParcel(source);
-            mDurations = readLongSparseLongArrayFromParcel(source);
-            mProxyUids = readLongSparseLongArrayFromParcel(source);
-            mProxyPackageNames = readLongSparseStringArrayFromParcel(source);
-        }
-
-        public static final @android.annotation.NonNull Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
-            @Override public OpEntry createFromParcel(Parcel source) {
-                return new OpEntry(source);
+        public static final @NonNull Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
+            @Override
+            public @NonNull OpEntry createFromParcel(@NonNull Parcel parcel) {
+                return OpEntry.createFromParcel(parcel);
             }
 
-            @Override public OpEntry[] newArray(int size) {
+            @Override
+            public @NonNull OpEntry[] newArray(int size) {
                 return new OpEntry[size];
             }
         };
@@ -4428,7 +5041,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param ops The set of operations you are interested in, or null if you want all of them.
      * @hide
@@ -4452,7 +5065,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param ops The set of operations you are interested in, or null if you want all of them.
      * @hide
@@ -4474,7 +5087,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param uid The uid of the application of interest.
      * @param packageName The name of the application of interest.
@@ -4507,7 +5120,7 @@
      * state due to UID policy or because it's controlled by a different master op.
      *
      * Use {@link #unsafeCheckOp(String, int, String)}} or
-     * {@link #noteOp(String, int, String, String)} if the effective mode is needed.
+     * {@link #noteOp(String, int, String, String, String)} if the effective mode is needed.
      *
      * @param uid The uid of the application of interest.
      * @param packageName The name of the application of interest.
@@ -4897,8 +5510,8 @@
      *
      * @see #isOperationActive
      * @see #stopWatchingActive
-     * @see #startOp(int, int, String, boolean, String)
-     * @see #finishOp(int, int, String)
+     * @see #startOp(int, int, String, boolean, String, String)
+     * @see #finishOp(int, int, String, String)
      */
     // TODO: Uncomment below annotation once b/73559440 is fixed
     // @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
@@ -4948,8 +5561,8 @@
      *
      * @see #isOperationActive
      * @see #startWatchingActive
-     * @see #startOp(int, int, String, boolean, String)
-     * @see #finishOp(int, int, String)
+     * @see #startOp(int, int, String, boolean, String, String)
+     * @see #finishOp(int, int, String, String)
      */
     public void stopWatchingActive(@NonNull OnOpActiveChangedListener callback) {
         synchronized (mActiveWatchers) {
@@ -4979,7 +5592,7 @@
      *
      * @see #startWatchingActive(int[], OnOpActiveChangedListener)
      * @see #stopWatchingNoted(OnOpNotedListener)
-     * @see #noteOp(String, int, String, String)
+     * @see #noteOp(String, int, String, String, String)
      *
      * @hide
      */
@@ -5011,7 +5624,7 @@
      * Unregistering a non-registered callback has no effect.
      *
      * @see #startWatchingNoted(int[], OnOpNotedListener)
-     * @see #noteOp(String, int, String, String)
+     * @see #noteOp(String, int, String, String, String)
      *
      * @hide
      */
@@ -5047,15 +5660,15 @@
     /**
      * Do a quick check for whether an application might be able to perform an operation.
      * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String,
-     * String)} or {@link #startOp(String, int, String, String)} for your actual security checks,
-     * which also ensure that the given uid and package name are consistent. This function can just
-     * be used for a quick check to see if an operation has been disabled for the application,
-     * as an early reject of some work.  This does not modify the time stamp or other data
-     * about the operation.
+     * String, String)} or {@link #startOp(String, int, String, String, String)} for your actual
+     * security checks, which also ensure that the given uid and package name are consistent. This
+     * function can just be used for a quick check to see if an operation has been disabled for the
+     * application, as an early reject of some work.  This does not modify the time stamp or other
+     * data about the operation.
      *
      * <p>Important things this will not do (which you need to ultimate use
-     * {@link #noteOp(String, int, String, String)} or
-     * {@link #startOp(String, int, String, String)} to cover):</p>
+     * {@link #noteOp(String, int, String, String, String)} or
+     * {@link #startOp(String, int, String, String, String)} to cover):</p>
      * <ul>
      *     <li>Verifying the uid and package are consistent, so callers can't spoof
      *     their identity.</li>
@@ -5126,35 +5739,37 @@
     }
 
     /**
-     * @deprecated Use {@link #noteOp(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOp(String, int, String, String, String)} instead
      */
     @Deprecated
     public int noteOp(@NonNull String op, int uid, @NonNull String packageName) {
-        return noteOp(op, uid, packageName, null);
+        return noteOp(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteOp(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOp(String, int, String, String, String)} instead
      *
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String)} instead")
+            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String, "
+            + "java.lang.String)} instead")
     @Deprecated
     public int noteOp(int op) {
-        return noteOp(op, Process.myUid(), mContext.getOpPackageName(), null);
+        return noteOp(op, Process.myUid(), mContext.getOpPackageName(), null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteOp(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOp(String, int, String, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String)} instead")
+            + "#noteOp(java.lang.String, int, java.lang.String, java.lang.String, "
+            + "java.lang.String)} instead")
     public int noteOp(int op, int uid, @Nullable String packageName) {
-        return noteOp(op, uid, packageName, null);
+        return noteOp(op, uid, packageName, null, null);
     }
 
     /**
@@ -5167,6 +5782,7 @@
      * @param op The operation to note.  One of the OPSTR_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5176,8 +5792,8 @@
      * @throws SecurityException If the app has been configured to crash on this op.
      */
     public int noteOp(@NonNull String op, int uid, @Nullable String packageName,
-            @Nullable String message) {
-        return noteOp(strOpToOp(op), uid, packageName, message);
+            @Nullable String featureId, @Nullable String message) {
+        return noteOp(strOpToOp(op), uid, packageName, featureId, message);
     }
 
     /**
@@ -5190,6 +5806,7 @@
      * @param op The operation to note.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5200,8 +5817,9 @@
      *
      * @hide
      */
-    public int noteOp(int op, int uid, @Nullable String packageName, @Nullable String message) {
-        final int mode = noteOpNoThrow(op, uid, packageName, message);
+    public int noteOp(int op, int uid, @Nullable String packageName, @Nullable String featureId,
+            @Nullable String message) {
+        final int mode = noteOpNoThrow(op, uid, packageName, featureId, message);
         if (mode == MODE_ERRORED) {
             throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
         }
@@ -5209,27 +5827,28 @@
     }
 
     /**
-     * @deprecated Use {@link #noteOpNoThrow(String, int, String, String)} instead
+     * @deprecated Use {@link #noteOpNoThrow(String, int, String, String, String)} instead
      */
     @Deprecated
     public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
-        return noteOpNoThrow(op, uid, packageName, null);
+        return noteOpNoThrow(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteOpNoThrow(int, int, String, String)} instead
+     * @deprecated Use {@link #noteOpNoThrow(int, int, String, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteOpNoThrow(java.lang.String, int, java.lang.String, java.lang.String)} instead")
+            + "#noteOpNoThrow(java.lang.String, int, java.lang.String, java.lang.String, "
+            + "java.lang.String)} instead")
     public int noteOpNoThrow(int op, int uid, String packageName) {
-        return noteOpNoThrow(op, uid, packageName, null);
+        return noteOpNoThrow(op, uid, packageName, null, null);
     }
 
     /**
-     * Like {@link #noteOp(String, int, String, String)} but instead of throwing a
+     * Like {@link #noteOp(String, int, String, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to note.  One of the OPSTR_* constants.
@@ -5242,17 +5861,18 @@
      * causing the app to crash).
      */
     public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
-            @Nullable String message) {
-        return noteOpNoThrow(strOpToOp(op), uid, packageName, message);
+            @Nullable String feature, @Nullable String message) {
+        return noteOpNoThrow(strOpToOp(op), uid, packageName, feature, message);
     }
 
     /**
-     * Like {@link #noteOp(String, int, String, String)} but instead of throwing a
+     * Like {@link #noteOp(String, int, String, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to note.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5262,11 +5882,11 @@
      * @hide
      */
     public int noteOpNoThrow(int op, int uid, @Nullable String packageName,
-            @Nullable String message) {
+            @Nullable String featureId, @Nullable String message) {
         try {
-            int mode = mService.noteOperation(op, uid, packageName);
+            int mode = mService.noteOperation(op, uid, packageName, featureId);
             if (mode == MODE_ALLOWED) {
-                markAppOpNoted(uid, packageName, op, message);
+                markAppOpNoted(uid, packageName, op, featureId, message);
             }
 
             return mode;
@@ -5276,23 +5896,24 @@
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOp(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOp(String, String, int, String, String)} instead
      */
     @Deprecated
     public int noteProxyOp(@NonNull String op, @NonNull String proxiedPackageName) {
-        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null);
+        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOp(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOp(String, String, int, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
-            + "#noteProxyOp(java.lang.String, java.lang.String, int, java.lang.String)} instead")
+            + "#noteProxyOp(java.lang.String, java.lang.String, int, java.lang.String, "
+            + "java.lang.String)} instead")
     public int noteProxyOp(int op, @Nullable String proxiedPackageName) {
-        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null);
+        return noteProxyOp(op, proxiedPackageName, Binder.getCallingUid(), null, null);
     }
 
     /**
@@ -5304,6 +5925,8 @@
      * @param op The operation to note. One of the OP_* constants.
      * @param proxiedPackageName The name of the application calling into the proxy application.
      * @param proxiedUid The uid of the proxied application
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
@@ -5315,8 +5938,9 @@
      * @hide
      */
     public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid,
-            @Nullable String message) {
-        int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, message);
+            @Nullable String proxiedFeatureId, @Nullable String message) {
+        int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, proxiedFeatureId,
+                message);
         if (mode == MODE_ERRORED) {
             throw new SecurityException("Proxy package " + mContext.getOpPackageName()
                     + " from uid " + Process.myUid() + " or calling package " + proxiedPackageName
@@ -5334,6 +5958,8 @@
      * @param op The operation to note. One of the OPSTR_* constants.
      * @param proxiedPackageName The name of the application calling into the proxy application.
      * @param proxiedUid The uid of the proxied application
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
@@ -5343,29 +5969,30 @@
      * op.
      */
     public int noteProxyOp(@NonNull String op, @Nullable String proxiedPackageName, int proxiedUid,
-            @Nullable String message) {
-        return noteProxyOp(strOpToOp(op), proxiedPackageName, proxiedUid, message);
+            @Nullable String proxiedFeatureId, @Nullable String message) {
+        return noteProxyOp(strOpToOp(op), proxiedPackageName, proxiedUid, proxiedFeatureId,
+                message);
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String, String)} instead
      */
     @Deprecated
     public int noteProxyOpNoThrow(@NonNull String op, @NonNull String proxiedPackageName) {
-        return noteProxyOpNoThrow(op, proxiedPackageName, Binder.getCallingUid(), null);
+        return noteProxyOpNoThrow(op, proxiedPackageName, Binder.getCallingUid(), null, null);
     }
 
     /**
-     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String)} instead
+     * @deprecated Use {@link #noteProxyOpNoThrow(String, String, int, String, String)} instead
      */
     @Deprecated
     public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
             int proxiedUid) {
-        return noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, null);
+        return noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, null, null);
     }
 
     /**
-     * Like {@link #noteProxyOp(String, String, int, String)} but instead
+     * Like {@link #noteProxyOp(String, String, int, String, String)} but instead
      * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * <p>This API requires package with the {@code proxiedPackageName} to belong to
@@ -5374,37 +6001,43 @@
      * @param op The op to note
      * @param proxiedPackageName The package to note the op for
      * @param proxiedUid The uid the package belongs to
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      */
     public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
-            int proxiedUid, @Nullable String message) {
-        return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid, message);
+            int proxiedUid, @Nullable String proxiedFeatureId, @Nullable String message) {
+        return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid,
+                proxiedFeatureId, message);
     }
 
     /**
-     * Like {@link #noteProxyOp(int, String, int, String)} but instead
+     * Like {@link #noteProxyOp(int, String, int, String, String)} but instead
      * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The op to note
      * @param proxiedPackageName The package to note the op for or {@code null} if the op should be
      *                           noted for the "android" package
      * @param proxiedUid The uid the package belongs to
+     * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
+     *                           feature
      * @param message A message describing the reason the op was noted
      *
      * @hide
      */
     public int noteProxyOpNoThrow(int op, @Nullable String proxiedPackageName, int proxiedUid,
-            @Nullable String message) {
+            @Nullable String proxiedFeatureId, @Nullable String message) {
         int myUid = Process.myUid();
 
         try {
-            int mode = mService.noteProxyOperation(op, myUid, mContext.getOpPackageName(),
-                    proxiedUid, proxiedPackageName);
+            int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
+                    proxiedFeatureId, myUid, mContext.getOpPackageName(),
+                    mContext.getFeatureId());
             if (mode == MODE_ALLOWED
                     // Only collect app-ops when the proxy is trusted
                     && mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1, myUid)
                     == PackageManager.PERMISSION_GRANTED) {
-                markAppOpNoted(proxiedUid, proxiedPackageName, op, message);
+                markAppOpNoted(proxiedUid, proxiedPackageName, op, proxiedFeatureId, message);
             }
 
             return mode;
@@ -5416,15 +6049,15 @@
     /**
      * Do a quick check for whether an application might be able to perform an operation.
      * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String,
-     * String)} or {@link #startOp(int, int, String, boolean, String)} for your actual security
-     * checks, which also ensure that the given uid and package name are consistent. This function
-     * can just be used for a quick check to see if an operation has been disabled for the
-     * application, as an early reject of some work.  This does not modify the time stamp or other
-     * data about the operation.
+     * String, String)} or {@link #startOp(int, int, String, boolean, String, String)} for your
+     * actual security checks, which also ensure that the given uid and package name are consistent.
+     * This function can just be used for a quick check to see if an operation has been disabled for
+     * the application, as an early reject of some work.  This does not modify the time stamp or
+     * other data about the operation.
      *
      * <p>Important things this will not do (which you need to ultimate use
-     * {@link #noteOp(String, int, String, String)} or
-     * {@link #startOp(int, int, String, boolean, String)} to cover):</p>
+     * {@link #noteOp(String, int, String, String, String)} or
+     * {@link #startOp(int, int, String, boolean, String, String)} to cover):</p>
      * <ul>
      *     <li>Verifying the uid and package are consistent, so callers can't spoof
      *     their identity.</li>
@@ -5534,41 +6167,41 @@
 
 
     /**
-     * @deprecated use {@link #startOp(String, int, String, String)} instead
+     * @deprecated use {@link #startOp(String, int, String, String, String)} instead
      */
     @Deprecated
     public int startOp(@NonNull String op, int uid, @NonNull String packageName) {
-        return startOp(op, uid, packageName, null);
+        return startOp(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOp(int, int, String, boolean, String)} instead
+     * @deprecated Use {@link #startOp(int, int, String, boolean, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public int startOp(int op) {
-        return startOp(op, Process.myUid(), mContext.getOpPackageName(), false, null);
+        return startOp(op, Process.myUid(), mContext.getOpPackageName(), false, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOp(int, int, String, boolean, String)} instead
+     * @deprecated Use {@link #startOp(int, int, String, boolean, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public int startOp(int op, int uid, String packageName) {
-        return startOp(op, uid, packageName, false, null);
+        return startOp(op, uid, packageName, false, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOp(int, int, String, boolean, String)} instead
+     * @deprecated Use {@link #startOp(int, int, String, boolean, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public int startOp(int op, int uid, String packageName, boolean startIfModeDefault) {
-        return startOp(op, uid, packageName, startIfModeDefault, null);
+        return startOp(op, uid, packageName, startIfModeDefault, null, null);
     }
 
     /**
@@ -5577,6 +6210,7 @@
      * @param op The operation to start.  One of the OPSTR_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message Description why op was started
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5587,8 +6221,8 @@
      * the package is not in the passed in UID.
      */
     public int startOp(@NonNull String op, int uid, @Nullable String packageName,
-            @Nullable String message) {
-        return startOp(strOpToOp(op), uid, packageName, false, message);
+            @NonNull String featureId, @Nullable String message) {
+        return startOp(strOpToOp(op), uid, packageName, false, featureId, message);
     }
 
     /**
@@ -5597,6 +6231,7 @@
      * @param op The operation to start.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
      * @param message Description why op was started
      *
@@ -5610,8 +6245,9 @@
      * @hide
      */
     public int startOp(int op, int uid, @Nullable String packageName, boolean startIfModeDefault,
-            @Nullable String message) {
-        final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault, message);
+            @NonNull String featureId, @Nullable String message) {
+        final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault, featureId,
+                message);
         if (mode == MODE_ERRORED) {
             throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
         }
@@ -5619,40 +6255,41 @@
     }
 
     /**
-     * @deprecated use {@link #startOpNoThrow(String, int, String, String)} instead
+     * @deprecated use {@link #startOpNoThrow(String, int, String, String, String)} instead
      */
     @Deprecated
     public int startOpNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
-        return startOpNoThrow(op, uid, packageName, null);
+        return startOpNoThrow(op, uid, packageName, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String} instead
+     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String, String} instead
      *
      * @hide
      */
     @Deprecated
     public int startOpNoThrow(int op, int uid, String packageName) {
-        return startOpNoThrow(op, uid, packageName, false, null);
+        return startOpNoThrow(op, uid, packageName, false, null, null);
     }
 
     /**
-     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String} instead
+     * @deprecated Use {@link #startOpNoThrow(int, int, String, boolean, String, String} instead
      *
      * @hide
      */
     @Deprecated
     public int startOpNoThrow(int op, int uid, String packageName, boolean startIfModeDefault) {
-        return startOpNoThrow(op, uid, packageName, startIfModeDefault, null);
+        return startOpNoThrow(op, uid, packageName, startIfModeDefault, null, null);
     }
 
     /**
-     * Like {@link #startOp(String, int, String, String)} but instead of throwing a
+     * Like {@link #startOp(String, int, String, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to start.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param message Description why op was started
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -5660,17 +6297,18 @@
      * causing the app to crash).
      */
     public int startOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
-            @Nullable String message) {
-        return startOpNoThrow(strOpToOp(op), uid, packageName, false, message);
+            @NonNull String featureId, @Nullable String message) {
+        return startOpNoThrow(strOpToOp(op), uid, packageName, false, featureId, message);
     }
 
     /**
-     * Like {@link #startOp(int, int, String, boolean, String)} but instead of throwing a
+     * Like {@link #startOp(int, int, String, boolean, String, String)} but instead of throwing a
      * {@link SecurityException} it returns {@link #MODE_ERRORED}.
      *
      * @param op The operation to start.  One of the OP_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The feature in the app or {@code null} for default feature
      * @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
      * @param message Description why op was started
      *
@@ -5681,12 +6319,12 @@
      * @hide
      */
     public int startOpNoThrow(int op, int uid, @NonNull String packageName,
-            boolean startIfModeDefault, @Nullable String message) {
+            boolean startIfModeDefault, @Nullable String featureId, @Nullable String message) {
         try {
             int mode = mService.startOperation(getToken(mService), op, uid, packageName,
-                    startIfModeDefault);
+                    featureId, startIfModeDefault);
             if (mode == MODE_ALLOWED) {
-                markAppOpNoted(uid, packageName, op, message);
+                markAppOpNoted(uid, packageName, op, featureId, message);
             }
 
             return mode;
@@ -5696,36 +6334,54 @@
     }
 
     /**
-     * @deprecated Use {@link #finishOp(String, int, String)} instead
+     * @deprecated Use {@link #finishOp(String, int, String, String)} instead
      *
      * @hide
      */
     @Deprecated
     public void finishOp(int op) {
-        finishOp(op, Process.myUid(), mContext.getOpPackageName());
+        finishOp(op, Process.myUid(), mContext.getOpPackageName(), null);
     }
 
     /**
-     * Report that an application is no longer performing an operation that had previously
-     * been started with {@link #startOp(String, int, String, String)}.  There is no validation of
-     * input or result; the parameters supplied here must be the exact same ones previously passed
-     * in when starting the operation.
+     * @deprecated Use {@link #finishOp(String, int, String, String)} instead
      */
     public void finishOp(@NonNull String op, int uid, @NonNull String packageName) {
-        finishOp(strOpToOp(op), uid, packageName);
+        finishOp(strOpToOp(op), uid, packageName, null);
     }
 
     /**
      * Report that an application is no longer performing an operation that had previously
-     * been started with {@link #startOp(int, int, String, boolean, String)}. There is no
+     * been started with {@link #startOp(String, int, String, String, String)}.  There is no
+     * validation of input or result; the parameters supplied here must be the exact same ones
+     * previously passed in when starting the operation.
+     */
+    public void finishOp(@NonNull String op, int uid, @NonNull String packageName,
+            @Nullable String featureId) {
+        finishOp(strOpToOp(op), uid, packageName, featureId);
+    }
+
+    /**
+     * @deprecated Use {@link #finishOp(int, int, String, String)} instead
+     *
+     * @hide
+     */
+    public void finishOp(int op, int uid, @NonNull String packageName) {
+        finishOp(op, uid, packageName, null);
+    }
+
+    /**
+     * Report that an application is no longer performing an operation that had previously
+     * been started with {@link #startOp(int, int, String, boolean, String, String)}. There is no
      * validation of input or result; the parameters supplied here must be the exact same ones
      * previously passed in when starting the operation.
      *
      * @hide
      */
-    public void finishOp(int op, int uid, @NonNull String packageName) {
+    public void finishOp(int op, int uid, @NonNull String packageName,
+            @Nullable String featureId) {
         try {
-            mService.finishOperation(getToken(mService), op, uid, packageName);
+            mService.finishOperation(getToken(mService), op, uid, packageName, featureId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -5737,8 +6393,8 @@
      * If you don't hold the {@code android.Manifest.permission#WATCH_APPOPS}
      * permission you can query only for your UID.
      *
-     * @see #finishOp(String, int, String)
-     * @see #startOp(String, int, String, String)
+     * @see #finishOp(String, int, String, String)
+     * @see #startOp(String, int, String, String, String)
      */
     public boolean isOpActive(@NonNull String op, int uid, @NonNull String packageName) {
         return isOperationActive(strOpToOp(op), uid, packageName);
@@ -5766,9 +6422,10 @@
      */
     public static class PausedNotedAppOpsCollection {
         final int mUid;
-        final @Nullable long[] mCollectedNotedAppOps;
+        final @Nullable ArrayMap<String, long[]> mCollectedNotedAppOps;
 
-        PausedNotedAppOpsCollection(int uid, @Nullable long[] collectedNotedAppOps) {
+        PausedNotedAppOpsCollection(int uid, @Nullable ArrayMap<String,
+                long[]> collectedNotedAppOps) {
             mUid = uid;
             mCollectedNotedAppOps = collectedNotedAppOps;
         }
@@ -5786,7 +6443,8 @@
     public static @Nullable PausedNotedAppOpsCollection pauseNotedAppOpsCollection() {
         Integer previousUid = sBinderThreadCallingUid.get();
         if (previousUid != null) {
-            long[] previousCollectedNotedAppOps = sAppOpsNotedInThisBinderTransaction.get();
+            ArrayMap<String, long[]> previousCollectedNotedAppOps =
+                    sAppOpsNotedInThisBinderTransaction.get();
 
             sBinderThreadCallingUid.remove();
             sAppOpsNotedInThisBinderTransaction.remove();
@@ -5832,8 +6490,12 @@
     /**
      * Mark an app-op as noted
      */
-    private void markAppOpNoted(int uid, @NonNull String packageName, int code,
-            @Nullable String message) {
+    private void markAppOpNoted(int uid, @Nullable String packageName, int code,
+            @Nullable String featureId, @Nullable String message) {
+        if (packageName == null) {
+            packageName = "android";
+        }
+
         // check it the appops needs to be collected and cache result
         if (sAppOpsToNote[code] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
             boolean shouldCollectNotes;
@@ -5860,7 +6522,7 @@
             if (sNotedAppOpsCollector != null && uid == Process.myUid() && packageName.equals(
                     ActivityThread.currentOpPackageName())) {
                 // This app is noting an app-op for itself. Deliver immediately.
-                sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(code));
+                sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(code, featureId));
 
                 return;
             }
@@ -5869,18 +6531,24 @@
         if (binderUid != null && binderUid == uid) {
             // If this is inside of a two-way binder call: Delivered to caller via
             // {@link #prefixParcelWithAppOpsIfNeeded}
-            long[] appOpsNotedInThisBinderTransaction;
+            // We are inside of a two-way binder call. Delivered to caller via
+            // {@link #prefixParcelWithAppOpsIfNeeded}
+            ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
+            if (appOpsNoted == null) {
+                appOpsNoted = new ArrayMap<>(1);
+                sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
+            }
 
-            appOpsNotedInThisBinderTransaction = sAppOpsNotedInThisBinderTransaction.get();
-            if (appOpsNotedInThisBinderTransaction == null) {
-                appOpsNotedInThisBinderTransaction = new long[2];
-                sAppOpsNotedInThisBinderTransaction.set(appOpsNotedInThisBinderTransaction);
+            long[] appOpsNotedForFeature = appOpsNoted.get(featureId);
+            if (appOpsNotedForFeature == null) {
+                appOpsNotedForFeature = new long[2];
+                appOpsNoted.put(featureId, appOpsNotedForFeature);
             }
 
             if (code < 64) {
-                appOpsNotedInThisBinderTransaction[0] |= 1L << code;
+                appOpsNotedForFeature[0] |= 1L << code;
             } else {
-                appOpsNotedInThisBinderTransaction[1] |= 1L << (code - 64);
+                appOpsNotedForFeature[1] |= 1L << (code - 64);
             }
         } else {
             // Cannot deliver the note synchronous: Hence send it to the system server to
@@ -5892,7 +6560,8 @@
 
             long token = Binder.clearCallingIdentity();
             try {
-                mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code, message);
+                mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code,
+                        featureId, message);
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             } finally {
@@ -5912,14 +6581,21 @@
      * @hide
      */
     public static void prefixParcelWithAppOpsIfNeeded(@NonNull Parcel p) {
-        long[] notedAppOps = sAppOpsNotedInThisBinderTransaction.get();
-        if (notedAppOps == null || (notedAppOps[0] == 0 && notedAppOps[1] == 0)) {
+        ArrayMap<String, long[]> notedAppOps = sAppOpsNotedInThisBinderTransaction.get();
+        if (notedAppOps == null) {
             return;
         }
 
         p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);
-        p.writeLong(notedAppOps[0]);
-        p.writeLong(notedAppOps[1]);
+
+        int numFeatureWithNotesAppOps = notedAppOps.size();
+        p.writeInt(numFeatureWithNotesAppOps);
+
+        for (int i = 0; i < numFeatureWithNotesAppOps; i++) {
+            p.writeString(notedAppOps.keyAt(i));
+            p.writeLong(notedAppOps.valueAt(i)[0]);
+            p.writeLong(notedAppOps.valueAt(i)[1]);
+        }
     }
 
     /**
@@ -5928,26 +6604,28 @@
      * <p>This is called on the calling side of a two way binder transaction just after the
      * transaction returns.
      *
-     * <p>Note: Make sure to keep frameworks/native/libs/binder/Status.cpp::readAndLogNotedAppops
-     * in sync.
-     *
      * @param p The parcel to read from
      *
      * @hide
      */
     public static void readAndLogNotedAppops(@NonNull Parcel p) {
-        long[] rawNotedAppOps = new long[2];
-        rawNotedAppOps[0] = p.readLong();
-        rawNotedAppOps[1] = p.readLong();
+        int numFeaturesWithNotedAppOps = p.readInt();
 
-        if (rawNotedAppOps[0] != 0 || rawNotedAppOps[1] != 0) {
-            BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);
+        for (int i = 0; i < numFeaturesWithNotedAppOps; i++) {
+            String featureId = p.readString();
+            long[] rawNotedAppOps = new long[2];
+            rawNotedAppOps[0] = p.readLong();
+            rawNotedAppOps[1] = p.readLong();
 
-            synchronized (sLock) {
-                for (int code = notedAppOps.nextSetBit(0); code != -1;
-                        code = notedAppOps.nextSetBit(code + 1)) {
-                    if (sNotedAppOpsCollector != null) {
-                        sNotedAppOpsCollector.onNoted(new SyncNotedAppOp(code));
+            if (rawNotedAppOps[0] != 0 || rawNotedAppOps[1] != 0) {
+                BitSet notedAppOps = BitSet.valueOf(rawNotedAppOps);
+
+                synchronized (sLock) {
+                    for (int code = notedAppOps.nextSetBit(0); code != -1;
+                            code = notedAppOps.nextSetBit(code + 1)) {
+                        if (sNotedAppOpsCollector != null) {
+                            sNotedAppOpsCollector.onNoted(new SyncNotedAppOp(code, featureId));
+                        }
                     }
                 }
             }
@@ -6134,8 +6812,8 @@
      *
      * @see #startWatchingActive(int[], OnOpActiveChangedListener)
      * @see #stopWatchingMode(OnOpChangedListener)
-     * @see #finishOp(int)
-     * @see #startOp(int, int, String, boolean, String)
+     * @see #finishOp(int, int, String, String)
+     * @see #startOp(int, int, String, boolean, String, String)
      *
      * @hide */
     @TestApi
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 19be6c9..bd7ef2a 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,10 +16,11 @@
 
 package android.app;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.util.SparseIntArray;
 
 import com.android.internal.util.function.QuadFunction;
-import com.android.internal.util.function.TriFunction;
 
 /**
  * App ops service local interface.
@@ -60,12 +61,14 @@
          *
          * @param code The op code to note.
          * @param uid The UID for which to note.
-         * @param packageName The package for which to note.
+         * @param packageName The package for which to note. {@code null} for system package.
+         * @param featureId Id of the feature in the package
          * @param superImpl The super implementation.
          * @return The app op note result.
          */
-        int noteOperation(int code, int uid, String packageName,
-                TriFunction<Integer, Integer, String, Integer> superImpl);
+        int noteOperation(int code, int uid, @Nullable String packageName,
+                @Nullable String featureId,
+                @NonNull QuadFunction<Integer, Integer, String, String, Integer> superImpl);
     }
 
     /**
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index df6533a..958ebae 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -25,7 +25,7 @@
 import com.android.internal.util.DataClass;
 
 /**
- * When an {@link AppOpsManager#noteOp(String, int, String, String) app-op is noted} and the
+ * When an {@link AppOpsManager#noteOp(String, int, String, String, String) app-op is noted} and the
  * app the app-op is noted for has a {@link AppOpsManager.AppOpsCollector} registered the note-event
  * needs to be delivered to the collector. Usually this is done via an {@link SyncNotedAppOp}, but
  * in some cases this is not possible. In this case an {@link AsyncNotedAppOp} is send to the system
@@ -51,6 +51,9 @@
      */
     private final @Nullable String mNotingPackageName;
 
+    /** {@link android.content.Context#createFeatureContext Feature} in the app */
+    private final @Nullable String mFeatureId;
+
     /** Message associated with the noteOp. This message is set by the app noting the op */
     private final @NonNull String mMessage;
 
@@ -66,14 +69,18 @@
 
 
 
-    // Code below generated by codegen v1.0.0.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
     //
     // To regenerate run:
     // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/AsyncNotedAppOp.java
     //
-    // CHECKSTYLE:OFF Generated code
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
 
     /**
      * Creates a new AsyncNotedAppOp.
@@ -83,7 +90,10 @@
      * @param notingUid
      *   Uid that noted the op
      * @param notingPackageName
-     *   Package that noted the op
+     *   Package that noted the op. {@code null} if the package name that noted the op could be not
+     *   be determined (e.g. when the op is noted from native code).
+     * @param featureId
+     *   {@link android.content.Context#createFeatureContext Feature} in the app
      * @param message
      *   Message associated with the noteOp. This message is set by the app noting the op
      * @param time
@@ -95,6 +105,7 @@
             @IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode,
             @IntRange(from = 0) int notingUid,
             @Nullable String notingPackageName,
+            @Nullable String featureId,
             @NonNull String message,
             @IntRange(from = 0) long time) {
         this.mOpCode = opCode;
@@ -107,6 +118,7 @@
                 IntRange.class, null, mNotingUid,
                 "from", 0);
         this.mNotingPackageName = notingPackageName;
+        this.mFeatureId = featureId;
         this.mMessage = message;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mMessage);
@@ -127,7 +139,8 @@
     }
 
     /**
-     * Package that noted the op
+     * Package that noted the op. {@code null} if the package name that noted the op could be not
+     * be determined (e.g. when the op is noted from native code).
      */
     @DataClass.Generated.Member
     public @Nullable String getNotingPackageName() {
@@ -135,6 +148,14 @@
     }
 
     /**
+     * {@link android.content.Context#createFeatureContext Feature} in the app
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getFeatureId() {
+        return mFeatureId;
+    }
+
+    /**
      * Message associated with the noteOp. This message is set by the app noting the op
      */
     @DataClass.Generated.Member
@@ -152,7 +173,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public boolean equals(Object o) {
+    public boolean equals(@Nullable Object o) {
         // You can override field equality logic by defining either of the methods like:
         // boolean fieldNameEquals(AsyncNotedAppOp other) { ... }
         // boolean fieldNameEquals(FieldType otherValue) { ... }
@@ -166,6 +187,7 @@
                 && mOpCode == that.mOpCode
                 && mNotingUid == that.mNotingUid
                 && java.util.Objects.equals(mNotingPackageName, that.mNotingPackageName)
+                && java.util.Objects.equals(mFeatureId, that.mFeatureId)
                 && java.util.Objects.equals(mMessage, that.mMessage)
                 && mTime == that.mTime;
     }
@@ -180,6 +202,7 @@
         _hash = 31 * _hash + mOpCode;
         _hash = 31 * _hash + mNotingUid;
         _hash = 31 * _hash + java.util.Objects.hashCode(mNotingPackageName);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mFeatureId);
         _hash = 31 * _hash + java.util.Objects.hashCode(mMessage);
         _hash = 31 * _hash + Long.hashCode(mTime);
         return _hash;
@@ -187,16 +210,18 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(android.os.Parcel dest, int flags) {
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
         byte flg = 0;
         if (mNotingPackageName != null) flg |= 0x4;
+        if (mFeatureId != null) flg |= 0x8;
         dest.writeByte(flg);
         dest.writeInt(mOpCode);
         dest.writeInt(mNotingUid);
         if (mNotingPackageName != null) dest.writeString(mNotingPackageName);
+        if (mFeatureId != null) dest.writeString(mFeatureId);
         dest.writeString(mMessage);
         dest.writeLong(mTime);
     }
@@ -205,6 +230,43 @@
     @DataClass.Generated.Member
     public int describeContents() { return 0; }
 
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AsyncNotedAppOp(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        int opCode = in.readInt();
+        int notingUid = in.readInt();
+        String notingPackageName = (flg & 0x4) == 0 ? null : in.readString();
+        String featureId = (flg & 0x8) == 0 ? null : in.readString();
+        String message = in.readString();
+        long time = in.readLong();
+
+        this.mOpCode = opCode;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mOpCode,
+                "from", 0,
+                "to", AppOpsManager._NUM_OP - 1);
+        this.mNotingUid = notingUid;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mNotingUid,
+                "from", 0);
+        this.mNotingPackageName = notingPackageName;
+        this.mFeatureId = featureId;
+        this.mMessage = message;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mMessage);
+        this.mTime = time;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mTime,
+                "from", 0);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
     @DataClass.Generated.Member
     public static final @NonNull Parcelable.Creator<AsyncNotedAppOp> CREATOR
             = new Parcelable.Creator<AsyncNotedAppOp>() {
@@ -214,31 +276,16 @@
         }
 
         @Override
-        @SuppressWarnings({"unchecked", "RedundantCast"})
-        public AsyncNotedAppOp createFromParcel(android.os.Parcel in) {
-            // You can override field unparcelling by defining methods like:
-            // static FieldType unparcelFieldName(Parcel in) { ... }
-
-            byte flg = in.readByte();
-            int opCode = in.readInt();
-            int notingUid = in.readInt();
-            String notingPackageName = (flg & 0x4) == 0 ? null : in.readString();
-            String message = in.readString();
-            long time = in.readLong();
-            return new AsyncNotedAppOp(
-                    opCode,
-                    notingUid,
-                    notingPackageName,
-                    message,
-                    time);
+        public AsyncNotedAppOp createFromParcel(@NonNull android.os.Parcel in) {
+            return new AsyncNotedAppOp(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1566503083973L,
-            codegenVersion = "1.0.0",
+            time = 1571327470155L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
-            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=91L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=91L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d5bc9b0..eb2b2bc 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -204,6 +204,9 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final String mOpPackageName;
 
+    /** If of feature this context is for */
+    private final @Nullable String mFeatureId;
+
     private final @NonNull ResourcesManager mResourcesManager;
     @UnsupportedAppUsage
     private @NonNull Resources mResources;
@@ -395,6 +398,12 @@
         return mOpPackageName != null ? mOpPackageName : getBasePackageName();
     }
 
+    /** @hide */
+    @Override
+    public @Nullable String getFeatureId() {
+        return mFeatureId;
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         if (mPackageInfo != null) {
@@ -2159,7 +2168,7 @@
         LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE);
         if (pi != null) {
-            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken,
+            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mActivityToken,
                     new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null);
 
             final int displayId = getDisplayId();
@@ -2187,15 +2196,15 @@
         if (packageName.equals("system") || packageName.equals("android")) {
             // The system resources are loaded in every application, so we can safely copy
             // the context without reloading Resources.
-            return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user,
-                    flags, null, null);
+            return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, null,
+                    mActivityToken, user, flags, null, null);
         }
 
         LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
         if (pi != null) {
-            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,
-                    flags, null, null);
+            ContextImpl c = new ContextImpl(this, mMainThread, pi, mFeatureId, null,
+                    mActivityToken, user, flags, null, null);
 
             final int displayId = getDisplayId();
 
@@ -2230,8 +2239,8 @@
         final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName);
         final String[] paths = mPackageInfo.getSplitPaths(splitName);
 
-        final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName,
-                mActivityToken, mUser, mFlags, classLoader, null);
+        final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
+                mFeatureId, splitName, mActivityToken, mUser, mFlags, classLoader, null);
 
         final int displayId = getDisplayId();
 
@@ -2254,8 +2263,8 @@
             throw new IllegalArgumentException("overrideConfiguration must not be null");
         }
 
-        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
-                mActivityToken, mUser, mFlags, mClassLoader, null);
+        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+                mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = getDisplayId();
         context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
@@ -2269,8 +2278,8 @@
             throw new IllegalArgumentException("display must not be null");
         }
 
-        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName,
-                mActivityToken, mUser, mFlags, mClassLoader, null);
+        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+                mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = display.getDisplayId();
         context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
@@ -2280,19 +2289,25 @@
     }
 
     @Override
+    public @NonNull Context createFeatureContext(@Nullable String featureId) {
+        return new ContextImpl(this, mMainThread, mPackageInfo, featureId, mSplitName,
+                mActivityToken, mUser, mFlags, mClassLoader, null);
+    }
+
+    @Override
     public Context createDeviceProtectedStorageContext() {
         final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
                 | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
-        return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
-                flags, mClassLoader, null);
+        return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
+                mActivityToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
     public Context createCredentialProtectedStorageContext() {
         final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
                 | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
-        return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser,
-                flags, mClassLoader, null);
+        return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
+                mActivityToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
@@ -2436,8 +2451,8 @@
     @UnsupportedAppUsage
     static ContextImpl createSystemContext(ActivityThread mainThread) {
         LoadedApk packageInfo = new LoadedApk(mainThread);
-        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
-                null, null);
+        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
+                0, null, null);
         context.setResources(packageInfo.getResources());
         context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                 context.mResourcesManager.getDisplayMetrics());
@@ -2454,7 +2469,7 @@
     static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
         final LoadedApk packageInfo = systemContext.mPackageInfo;
         ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
-                null, null, 0, null, null);
+                null, null, null, 0, null, null);
         context.setResources(createResources(null, packageInfo, null, displayId, null,
                 packageInfo.getCompatibilityInfo()));
         context.updateDisplay(displayId);
@@ -2477,8 +2492,8 @@
     static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
             String opPackageName) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
-        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
-                null, opPackageName);
+        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
+                0, null, opPackageName);
         context.setResources(packageInfo.getResources());
         return context;
     }
@@ -2505,8 +2520,8 @@
             }
         }
 
-        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
-                activityToken, null, 0, classLoader, null);
+        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null,
+                activityInfo.splitName, activityToken, null, 0, classLoader, null);
 
         // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
         displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
@@ -2534,9 +2549,9 @@
     }
 
     private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
-            @NonNull LoadedApk packageInfo, @Nullable String splitName,
-            @Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
-            @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
+            @NonNull LoadedApk packageInfo, @Nullable String featureId,
+            @Nullable String splitName, @Nullable IBinder activityToken, @Nullable UserHandle user,
+            int flags, @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
         mOuterContext = this;
 
         // If creator didn't specify which storage to use, use the default
@@ -2587,7 +2602,7 @@
         }
 
         mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
-
+        mFeatureId = featureId;
         mContentResolver = new ApplicationContentResolver(this, mainThread);
     }
 
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 905f475..96751db 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -18,7 +18,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.annotation.NonNull;
 import android.app.SharedElementCallback.OnSharedElementsReadyListener;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
@@ -70,13 +69,11 @@
     private Runnable mOnTransitionComplete;
 
     EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
-            ArrayList<String> sharedElementNames, boolean isReturning, boolean isCrossTask,
-            @NonNull Runnable onTransitionComplete) {
+            ArrayList<String> sharedElementNames, boolean isReturning, boolean isCrossTask) {
         super(activity.getWindow(), sharedElementNames,
                 getListener(activity, isReturning && !isCrossTask), isReturning);
         mActivity = activity;
         mIsCrossTask = isCrossTask;
-        mOnTransitionComplete = onTransitionComplete;
         setResultReceiver(resultReceiver);
         prepareEnter();
         Bundle resultReceiverBundle = new Bundle();
@@ -570,6 +567,14 @@
         return transition;
     }
 
+    public void runAfterTransitionsComplete(Runnable onTransitionComplete) {
+        if (!isTransitionRunning()) {
+            onTransitionsComplete();
+        } else {
+            mOnTransitionComplete = onTransitionComplete;
+        }
+    }
+
     @Override
     protected void onTransitionsComplete() {
         moveSharedElementsFromOverlay();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index dca00a2..31a29d4 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -351,10 +351,6 @@
     // Request a heap dump for the system server.
     void requestSystemServerHeapDump();
 
-    // Deprecated - This method is only used by a few internal components and it will soon start
-    // using bug report API (which will be restricted to a few, pre-defined apps).
-    // No new code should be calling it.
-    @UnsupportedAppUsage
     void requestBugReport(int bugreportType);
     void requestBugReportWithDescription(in @nullable String shareTitle,
                 in @nullable String shareDescription, int bugreportType);
@@ -364,7 +360,7 @@
      *  that are passed to this API as parameters
      *
      *  @param shareTitle should be a valid legible string less than 50 chars long
-     *  @param shareDescription should be less than 91 bytes when encoded into UTF-8 format
+     *  @param shareDescription should be less than 150 chars long
      *
      *  @throws IllegalArgumentException if shareTitle or shareDescription is too big or if the
      *          paremeters cannot be encoding to an UTF-8 charset.
@@ -372,13 +368,12 @@
     void requestTelephonyBugReport(in String shareTitle, in String shareDescription);
 
     /**
-     *  Deprecated - This method is only used by Wifi, and it will soon start using
-     *  bug report API.
+     *  This method is only used by Wifi.
      *
      *  Takes a minimal bugreport of Wifi-related state.
      *
      *  @param shareTitle should be a valid legible string less than 50 chars long
-     *  @param shareDescription should be less than 91 bytes when encoded into UTF-8 format
+     *  @param shareDescription should be less than 150 chars long
      *
      *  @throws IllegalArgumentException if shareTitle or shareDescription is too big or if the
      *          parameters cannot be encoding to an UTF-8 charset.
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 0ba1989..06288c0 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -158,7 +158,7 @@
      * @param activityToken Token of the size compatibility mode activity. It will be null when
      *                      switching to a activity that is not in size compatibility mode or the
      *                      configuration of the activity.
-     * @see com.android.server.wm.AppWindowToken#inSizeCompatMode
+     * @see com.android.server.wm.ActivityRecord#inSizeCompatMode
      */
     void onSizeCompatModeActivityChanged(int displayId, in IBinder activityToken);
 
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 58f6741..6dca5d9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1029,7 +1029,7 @@
      * Returns AutomaticZenRules owned by the caller.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      */
     public Map<String, AutomaticZenRule> getAutomaticZenRules() {
@@ -1053,7 +1053,7 @@
      * Returns the AutomaticZenRule with the given id, if it exists and the caller has access.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
@@ -1073,7 +1073,7 @@
      * Creates the given zen rule.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * @param automaticZenRule the rule to create.
@@ -1092,7 +1092,7 @@
      * Updates the given zen rule.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
@@ -1134,7 +1134,7 @@
      * Deletes the automatic zen rule with the given id.
      *
      * <p>
-     * Throws a SecurityException if policy access is granted to this package.
+     * Throws a SecurityException if policy access is not granted to this package.
      * See {@link #isNotificationPolicyAccessGranted}.
      *
      * <p>
diff --git a/core/java/android/app/SyncNotedAppOp.java b/core/java/android/app/SyncNotedAppOp.java
index f7b83d4..065d5de 100644
--- a/core/java/android/app/SyncNotedAppOp.java
+++ b/core/java/android/app/SyncNotedAppOp.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 import com.android.internal.annotations.Immutable;
 
@@ -33,6 +34,7 @@
 @Immutable
 public final class SyncNotedAppOp {
     private final int mOpCode;
+    private final @Nullable String mFeatureId;
 
     /**
      * @return The op that was noted.
@@ -42,14 +44,23 @@
     }
 
     /**
+     * @return The {@link android.content.Context#createFeatureContext Feature} in the app
+     */
+    public @Nullable String getFeatureId() {
+        return mFeatureId;
+    }
+
+    /**
      * Create a new sync op description
      *
      * @param opCode The op that was noted
      *
      * @hide
      */
-    public SyncNotedAppOp(@IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode) {
+    public SyncNotedAppOp(@IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode,
+            @Nullable String featureId) {
         mOpCode = opCode;
+        mFeatureId = featureId;
     }
 
     @Override
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e81dc1c..8350fa1 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -152,7 +152,7 @@
 import android.os.image.DynamicSystemManager;
 import android.os.image.IDynamicSystemService;
 import android.os.storage.StorageManager;
-import android.os.telephony.TelephonyRegistryManager;
+import android.telephony.TelephonyRegistryManager;
 import android.permission.PermissionControllerManager;
 import android.permission.PermissionManager;
 import android.print.IPrintManager;
@@ -611,7 +611,7 @@
             new CachedServiceFetcher<TelephonyRegistryManager>() {
                 @Override
                 public TelephonyRegistryManager createService(ContextImpl ctx) {
-                    return new TelephonyRegistryManager();
+                    return new TelephonyRegistryManager(ctx);
                 }});
 
         registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 8ea1ff5..ad671df 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6633,6 +6633,8 @@
      * The calling device admin must be a profile owner or device owner. If it is not, a security
      * exception will be thrown.
      *
+     * <p>NOTE: Performs disk I/O and shouldn't be called on the main thread.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param filter The IntentFilter for which a default handler is added.
      * @param activity The Activity that is added as default intent handler.
@@ -7203,7 +7205,8 @@
      * used, calling with an empty list only allows the built-in system services. Any non-system
      * accessibility service that's currently enabled must be included in the list.
      * <p>
-     * System accessibility services are always available to the user the list can't modify this.
+     * System accessibility services are always available to the user and this method can't
+     * disable them.
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageNames List of accessibility service package names.
      * @return {@code true} if the operation succeeded, or {@code false} if the list didn't
@@ -8348,6 +8351,24 @@
     }
 
     /**
+     * Called by device owners to set the user's master location setting.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+     * @param locationEnabled whether location should be enabled or disabled
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public void setLocationEnabled(@NonNull ComponentName admin, boolean locationEnabled) {
+        throwIfParentInstance("setLocationEnabled");
+        if (mService != null) {
+            try {
+                mService.setLocationEnabled(admin, locationEnabled);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
      * Called by profile or device owners to update {@link android.provider.Settings.Secure}
      * settings. Validation that the value of the setting is in the correct form for the setting
      * type should be performed by the caller.
@@ -8376,6 +8397,11 @@
      * all users.
      * </strong>
      *
+     * <strong>Note: Starting from Android R, apps should no longer call this method with the
+     * setting {@link android.provider.Settings.Secure#LOCATION_MODE}, which is deprecated. Instead,
+     * device owners should call {@link #setLocationEnabled(ComponentName, boolean)}.
+     * </strong>
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param setting The name of the setting to update.
      * @param value The value to update the setting to.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7d2c54e..6b50522 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -258,6 +258,8 @@
     void setSystemSetting(in ComponentName who, in String setting, in String value);
     void setSecureSetting(in ComponentName who, in String setting, in String value);
 
+    void setLocationEnabled(in ComponentName who, boolean locationEnabled);
+
     boolean setTime(in ComponentName who, long millis);
     boolean setTimeZone(in ComponentName who, String timeZone);
 
diff --git a/core/java/android/app/admin/PasswordMetrics.java b/core/java/android/app/admin/PasswordMetrics.java
index d9bfde5..0ecfca7 100644
--- a/core/java/android/app/admin/PasswordMetrics.java
+++ b/core/java/android/app/admin/PasswordMetrics.java
@@ -73,6 +73,11 @@
     // consider it a complex PIN/password.
     public static final int MAX_ALLOWED_SEQUENCE = 3;
 
+    // One of CREDENTIAL_TYPE_NONE, CREDENTIAL_TYPE_PATTERN or CREDENTIAL_TYPE_PASSWORD.
+    // Note that this class still uses CREDENTIAL_TYPE_PASSWORD to represent both numeric PIN
+    // and alphabetic password. This is OK as long as this definition is only used internally,
+    // and the value never gets mixed up with credential types from other parts of the framework.
+    // TODO: fix this (ideally after we move logic to PasswordPolicy)
     public @CredentialType int credType;
     // Fields below only make sense when credType is PASSWORD.
     public int length = 0;
@@ -161,24 +166,26 @@
 
     public static final @NonNull Parcelable.Creator<PasswordMetrics> CREATOR
             = new Parcelable.Creator<PasswordMetrics>() {
-        public PasswordMetrics createFromParcel(Parcel in) {
-            int credType = in.readInt();
-            int length = in.readInt();
-            int letters = in.readInt();
-            int upperCase = in.readInt();
-            int lowerCase = in.readInt();
-            int numeric = in.readInt();
-            int symbols = in.readInt();
-            int nonLetter = in.readInt();
-            int nonNumeric = in.readInt();
-            int seqLength = in.readInt();
-            return new PasswordMetrics(credType, length, letters, upperCase, lowerCase, numeric,
-                    symbols, nonLetter, nonNumeric, seqLength);
-        }
+                @Override
+                public PasswordMetrics createFromParcel(Parcel in) {
+                    int credType = in.readInt();
+                    int length = in.readInt();
+                    int letters = in.readInt();
+                    int upperCase = in.readInt();
+                    int lowerCase = in.readInt();
+                    int numeric = in.readInt();
+                    int symbols = in.readInt();
+                    int nonLetter = in.readInt();
+                    int nonNumeric = in.readInt();
+                    int seqLength = in.readInt();
+                    return new PasswordMetrics(credType, length, letters, upperCase, lowerCase,
+                            numeric, symbols, nonLetter, nonNumeric, seqLength);
+                }
 
-        public PasswordMetrics[] newArray(int size) {
-            return new PasswordMetrics[size];
-        }
+                @Override
+                public PasswordMetrics[] newArray(int size) {
+                    return new PasswordMetrics[size];
+                }
     };
 
     /**
@@ -189,7 +196,7 @@
      * {@link com.android.internal.widget.LockPatternUtils#CREDENTIAL_TYPE_PASSWORD}.
      */
     public static PasswordMetrics computeForCredential(LockscreenCredential credential) {
-        if (credential.isPassword()) {
+        if (credential.isPassword() || credential.isPin()) {
             return PasswordMetrics.computeForPassword(credential.getCredential());
         } else if (credential.isPattern())  {
             return new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index f624446..ddc4932 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -16,10 +16,10 @@
 
 package android.app.timedetector;
 
-import android.app.timedetector.TimeSignal;
+import android.app.timedetector.PhoneTimeSuggestion;
 
 /**
- * System private API to comunicate with time detector service.
+ * System private API to communicate with time detector service.
  *
  * <p>Used by parts of the Android system with signals associated with the device's time to provide
  * information to the Time Detector Service.
@@ -32,5 +32,5 @@
  * {@hide}
  */
 interface ITimeDetectorService {
-  void suggestTime(in TimeSignal timeSignal);
+  void suggestPhoneTime(in PhoneTimeSuggestion timeSuggestion);
 }
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/core/java/android/app/timedetector/PhoneTimeSuggestion.aidl
similarity index 94%
rename from core/java/android/app/timedetector/TimeSignal.aidl
rename to core/java/android/app/timedetector/PhoneTimeSuggestion.aidl
index d2ec357..f5e2405 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.aidl
@@ -16,4 +16,4 @@
 
 package android.app.timedetector;
 
-parcelable TimeSignal;
\ No newline at end of file
+parcelable PhoneTimeSuggestion;
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
new file mode 100644
index 0000000..475a4aa
--- /dev/null
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -0,0 +1,137 @@
+/*
+ * 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.app.timedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.TimestampedValue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A time signal from a telephony source. The value consists of the number of milliseconds elapsed
+ * since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number
+ * was established. The elapsed realtime clock is considered accurate but volatile, so time signals
+ * must not be persisted across device resets.
+ *
+ * @hide
+ */
+public final class PhoneTimeSuggestion implements Parcelable {
+
+    public static final @NonNull Parcelable.Creator<PhoneTimeSuggestion> CREATOR =
+            new Parcelable.Creator<PhoneTimeSuggestion>() {
+                public PhoneTimeSuggestion createFromParcel(Parcel in) {
+                    return PhoneTimeSuggestion.createFromParcel(in);
+                }
+
+                public PhoneTimeSuggestion[] newArray(int size) {
+                    return new PhoneTimeSuggestion[size];
+                }
+            };
+
+    private final int mPhoneId;
+    @NonNull
+    private final TimestampedValue<Long> mUtcTime;
+    @Nullable
+    private ArrayList<String> mDebugInfo;
+
+    public PhoneTimeSuggestion(int phoneId, @NonNull TimestampedValue<Long> utcTime) {
+        mPhoneId = phoneId;
+        mUtcTime = Objects.requireNonNull(utcTime);
+    }
+
+    private static PhoneTimeSuggestion createFromParcel(Parcel in) {
+        int phoneId = in.readInt();
+        TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
+        PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId, utcTime);
+        @SuppressWarnings("unchecked")
+        ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
+        suggestion.mDebugInfo = debugInfo;
+        return suggestion;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mPhoneId);
+        dest.writeParcelable(mUtcTime, 0);
+        dest.writeList(mDebugInfo);
+    }
+
+    public int getPhoneId() {
+        return mPhoneId;
+    }
+
+    @NonNull
+    public TimestampedValue<Long> getUtcTime() {
+        return mUtcTime;
+    }
+
+    @NonNull
+    public List<String> getDebugInfo() {
+        return Collections.unmodifiableList(mDebugInfo);
+    }
+
+    /**
+     * Associates information with the instance that can be useful for debugging / logging. The
+     * information is present in {@link #toString()} but is not considered for
+     * {@link #equals(Object)} and {@link #hashCode()}.
+     */
+    public void addDebugInfo(String... debugInfos) {
+        if (mDebugInfo == null) {
+            mDebugInfo = new ArrayList<>();
+        }
+        mDebugInfo.addAll(Arrays.asList(debugInfos));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        PhoneTimeSuggestion that = (PhoneTimeSuggestion) o;
+        return mPhoneId == that.mPhoneId
+                && Objects.equals(mUtcTime, that.mUtcTime);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPhoneId, mUtcTime);
+    }
+
+    @Override
+    public String toString() {
+        return "PhoneTimeSuggestion{"
+                + "mPhoneId='" + mPhoneId + '\''
+                + ", mUtcTime=" + mUtcTime
+                + ", mDebugInfo=" + mDebugInfo
+                + '}';
+    }
+}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 052050d..334e958 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -45,12 +45,12 @@
      * signals are available such as those that come from more reliable sources or were
      * determined more recently.
      */
-    public void suggestTime(@NonNull TimeSignal timeSignal) {
+    public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
         if (DEBUG) {
-            Log.d(TAG, "suggestTime called: " + timeSignal);
+            Log.d(TAG, "suggestPhoneTime called: " + timeSuggestion);
         }
         try {
-            mITimeDetectorService.suggestTime(timeSignal);
+            mITimeDetectorService.suggestPhoneTime(timeSuggestion);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/timedetector/TimeSignal.java b/core/java/android/app/timedetector/TimeSignal.java
deleted file mode 100644
index b494260..0000000
--- a/core/java/android/app/timedetector/TimeSignal.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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.app.timedetector;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.TimestampedValue;
-
-import java.util.Objects;
-
-/**
- * A time signal from a named source. The value consists of the number of milliseconds elapsed since
- * 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number was
- * established. The elapsed realtime clock is considered accurate but volatile, so time signals
- * must not be persisted across device resets.
- *
- * @hide
- */
-public final class TimeSignal implements Parcelable {
-
-    public static final @android.annotation.NonNull Parcelable.Creator<TimeSignal> CREATOR =
-            new Parcelable.Creator<TimeSignal>() {
-                public TimeSignal createFromParcel(Parcel in) {
-                    return TimeSignal.createFromParcel(in);
-                }
-
-                public TimeSignal[] newArray(int size) {
-                    return new TimeSignal[size];
-                }
-            };
-
-    public static final String SOURCE_ID_NITZ = "nitz";
-
-    private final String mSourceId;
-    private final TimestampedValue<Long> mUtcTime;
-
-    public TimeSignal(String sourceId, TimestampedValue<Long> utcTime) {
-        mSourceId = Objects.requireNonNull(sourceId);
-        mUtcTime = Objects.requireNonNull(utcTime);
-    }
-
-    private static TimeSignal createFromParcel(Parcel in) {
-        String sourceId = in.readString();
-        TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
-        return new TimeSignal(sourceId, utcTime);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(mSourceId);
-        dest.writeParcelable(mUtcTime, 0);
-    }
-
-    @NonNull
-    public String getSourceId() {
-        return mSourceId;
-    }
-
-    @NonNull
-    public TimestampedValue<Long> getUtcTime() {
-        return mUtcTime;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        TimeSignal that = (TimeSignal) o;
-        return Objects.equals(mSourceId, that.mSourceId)
-                && Objects.equals(mUtcTime, that.mUtcTime);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mSourceId, mUtcTime);
-    }
-
-    @Override
-    public String toString() {
-        return "TimeSignal{"
-                + "mSourceId='" + mSourceId + '\''
-                + ", mUtcTime=" + mUtcTime
-                + '}';
-    }
-}
diff --git a/core/java/android/app/usage/EventList.java b/core/java/android/app/usage/EventList.java
index 8c03405..afdcbe6 100644
--- a/core/java/android/app/usage/EventList.java
+++ b/core/java/android/app/usage/EventList.java
@@ -79,6 +79,21 @@
     }
 
     /**
+     * Removes the event at the given index.
+     *
+     * @param index the index of the event to remove
+     * @return the event removed, or {@code null} if the index was out of bounds
+     */
+    public UsageEvents.Event remove(int index) {
+        try {
+            return mEvents.remove(index);
+        } catch (IndexOutOfBoundsException e) {
+            // catch and handle the exception here instead of throwing it to the client
+            return null;
+        }
+    }
+
+    /**
      * Finds the index of the first event whose timestamp is greater than or equal to the given
      * timestamp.
      *
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 5dbca12..4bf9c04 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -312,6 +312,11 @@
         public static final int VALID_FLAG_BITS = FLAG_IS_PACKAGE_INSTANT_APP;
 
         /**
+         * @hide
+         */
+        private static final int UNASSIGNED_TOKEN = -1;
+
+        /**
          * {@hide}
          */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -320,12 +325,22 @@
         /**
          * {@hide}
          */
+        public int mPackageToken = UNASSIGNED_TOKEN;
+
+        /**
+         * {@hide}
+         */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public String mClass;
 
         /**
          * {@hide}
          */
+        public int mClassToken = UNASSIGNED_TOKEN;
+
+        /**
+         * {@hide}
+         */
         public int mInstanceId;
 
         /**
@@ -336,11 +351,21 @@
         /**
          * {@hide}
          */
+        public int mTaskRootPackageToken = UNASSIGNED_TOKEN;
+
+        /**
+         * {@hide}
+         */
         public String mTaskRootClass;
 
         /**
          * {@hide}
          */
+        public int mTaskRootClassToken = UNASSIGNED_TOKEN;
+
+        /**
+         * {@hide}
+         */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public long mTimeStamp;
 
@@ -365,6 +390,11 @@
         public String mShortcutId;
 
         /**
+         * {@hide}
+         */
+        public int mShortcutIdToken = UNASSIGNED_TOKEN;
+
+        /**
          * Action type passed to ChooserActivity
          * Only present for {@link #CHOOSER_ACTION} event types.
          * {@hide}
@@ -401,6 +431,11 @@
          */
         public String mNotificationChannelId;
 
+        /**
+         * {@hide}
+         */
+        public int mNotificationChannelIdToken = UNASSIGNED_TOKEN;
+
         /** @hide */
         @EventFlags
         public int mFlags;
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 2c021cc..9d43dd3 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -35,6 +35,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 /**
@@ -52,6 +53,11 @@
     /**
      * {@hide}
      */
+    public int mPackageToken = -1;
+
+    /**
+     * {@hide}
+     */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public long mBeginTimeStamp;
 
@@ -143,6 +149,11 @@
     /**
      * {@hide}
      */
+    public SparseArray<SparseIntArray> mChooserCountsObfuscated = new SparseArray<>();
+
+    /**
+     * {@hide}
+     */
     public UsageStats() {
     }
 
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 30868bf..97e3f52 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -154,7 +154,7 @@
     }
 
     /**
-     * Returns the local name of the BLE device. The is a UTF-8 encoded string.
+     * Returns the local name of the BLE device. This is a UTF-8 encoded string.
      */
     @Nullable
     public String getDeviceName() {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 9dbfbc7..7de8793 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -834,6 +834,23 @@
     }
 
     /**
+     * Retrieves a Non-Nullable Context this provider is running in, this is intended to be called
+     * after {@link #onCreate}. When called before context was created, an IllegalStateException
+     * will be thrown.
+     * <p>
+     * Note A provider must be declared in the manifest and created automatically by the system,
+     * and context is only available after {@link #onCreate} is called.
+     */
+    @NonNull
+    public final Context requireContext() {
+        final Context ctx = getContext();
+        if (ctx == null) {
+            throw new IllegalStateException("Cannot find context from the provider.");
+        }
+        return ctx;
+    }
+
+    /**
      * Set the calling package, returning the current value (or {@code null})
      * which can be used later to restore the previous state.
      */
@@ -1469,9 +1486,8 @@
      * This method can be called from multiple threads, as described in
      * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
-     * @param uri The content:// URI of the insertion request. This must not be {@code null}.
+     * @param uri The content:// URI of the insertion request.
      * @param values A set of column_name/value pairs to add to the database.
-     *     This must not be {@code null}.
      * @return The URI for the newly inserted item.
      */
     @Override
@@ -1538,7 +1554,6 @@
      * @param uri The URI to query. This can potentially have a record ID if this
      * is an update request for a specific record.
      * @param values A set of column_name/value pairs to update in the database.
-     *     This must not be {@code null}.
      * @param selection An optional filter to match rows to update.
      * @return the number of rows affected.
      */
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 7c279fe..7f9ea76 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1765,7 +1765,7 @@
             stableProvider = null;
 
             return new AssetFileDescriptor(pfd, fd.getStartOffset(),
-                    fd.getDeclaredLength());
+                    fd.getDeclaredLength(), fd.getExtras());
 
         } catch (RemoteException e) {
             // Whatever, whatever, we'll go away.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e7e278f..9a9fc89 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -63,6 +63,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.provider.MediaStore;
+import android.telephony.TelephonyRegistryManager;
 import android.util.AttributeSet;
 import android.view.Display;
 import android.view.DisplayAdjustments;
@@ -74,6 +75,7 @@
 import android.view.textclassifier.TextClassificationManager;
 
 import com.android.internal.compat.IPlatformCompat;
+import com.android.internal.compat.IPlatformCompatNative;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -810,6 +812,17 @@
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 
+    /**
+     * <p>Features are used in complex apps to logically separate parts of the app. E.g. a
+     * blogging app might also have a instant messaging app built in.
+     *
+     * @return the feature id this context is for or {@code null} if this is the default
+     * feature.
+     */
+    public @Nullable String getFeatureId() {
+        return null;
+    }
+
     /** Return the full application info for this context's package. */
     public abstract ApplicationInfo getApplicationInfo();
 
@@ -3243,6 +3256,7 @@
             //@hide ROLE_CONTROLLER_SERVICE,
             CAMERA_SERVICE,
             //@hide: PLATFORM_COMPAT_SERVICE,
+            //@hide: PLATFORM_COMPAT_NATIVE_SERVICE,
             PRINT_SERVICE,
             CONSUMER_IR_SERVICE,
             //@hide: TRUST_SERVICE,
@@ -4620,6 +4634,14 @@
     public static final String PLATFORM_COMPAT_SERVICE = "platform_compat";
 
     /**
+     * Use with {@link android.os.ServiceManager.getService()} to retrieve a
+     * {@link IPlatformCompatNative} IBinder for native code communicating with the platform compat
+     * service.
+     * @hide
+     */
+    public static final String PLATFORM_COMPAT_NATIVE_SERVICE = "platform_compat_native";
+
+    /**
      * Service to capture a bugreport.
      * @see #getSystemService(String)
      * @see android.os.BugreportManager
@@ -4716,7 +4738,7 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
-     * {@link android.os.telephony.TelephonyRegistryManager}.
+     * {@link TelephonyRegistryManager}.
      * @hide
      */
     @SystemApi
@@ -5331,6 +5353,20 @@
     public abstract Context createDisplayContext(@NonNull Display display);
 
     /**
+     * Return a new Context object for the current Context but for a different feature in the app.
+     * Features can be used by complex apps to separate logical parts.
+     *
+     * @param featureId The feature id or {@code null} to create a context for the default feature.
+     *
+     * @return A {@link Context} for the feature
+     *
+     * @see #getFeatureId()
+     */
+    public @NonNull Context createFeatureContext(@Nullable String featureId) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Return a new Context object for the current Context but whose storage
      * APIs are backed by device-protected storage.
      * <p>
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 7993ea1..d5d0dce 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -158,6 +159,12 @@
         return mBase.getOpPackageName();
     }
 
+    /** @hide */
+    @Override
+    public @Nullable String getFeatureId() {
+        return mBase.getFeatureId();
+    }
+
     @Override
     public ApplicationInfo getApplicationInfo() {
         return mBase.getApplicationInfo();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index efb1c6a..4e7e713 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1134,6 +1134,18 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
     /**
+     * Activity Action: Dial a emergency number specified by the data.  This shows a
+     * UI with the number being dialed, allowing the user to explicitly
+     * initiate the call.
+     * <p>Input: If nothing, an empty emergency dialer is started; else {@link #getData}
+     * is a tel: URI of an explicit emergency phone number.
+     * <p>Output: nothing.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_DIAL_EMERGENCY = "android.intent.action.DIAL_EMERGENCY";
+    /**
      * Activity action: Perform a call to any number (emergency or not)
      * specified by the data.
      * <p>Input: {@link #getData} is URI of a phone number to be dialed or a
@@ -2666,6 +2678,9 @@
      * that application is first launched (that is the first time it is moved
      * out of the stopped state).  The data contains the name of the package.
      *
+     * <p>When the application is first launched, the application itself doesn't receive this
+     * broadcast.</p>
+     *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
      */
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index c3daad1..85f96fc 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -401,7 +401,8 @@
         }
 
         if (forDataDelivery) {
-            if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, message)
+            // TODO moltmann: Set correct feature id
+            if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, null, message)
                     != AppOpsManager.MODE_ALLOWED) {
                 return PERMISSION_DENIED_APP_OP;
             }
@@ -414,4 +415,4 @@
 
         return PERMISSION_GRANTED;
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java
index 8fcfe71..18d3ba3 100644
--- a/core/java/android/content/pm/AndroidTestBaseUpdater.java
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -55,15 +55,20 @@
     private static final long REMOVE_ANDROID_TEST_BASE = 133396946L;
 
     private static boolean isChangeEnabled(Package pkg) {
-        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
-                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
-        try {
-            return platformCompat.isChangeEnabled(REMOVE_ANDROID_TEST_BASE, pkg.applicationInfo);
-        } catch (RemoteException | NullPointerException e) {
-            Log.e(TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
+        // Do not ask platform compat for system apps to prevent a boot time regression in tests.
+        // b/142558883.
+        if (!pkg.applicationInfo.isSystemApp()) {
+            IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+                    ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+            try {
+                return platformCompat.isChangeEnabled(REMOVE_ANDROID_TEST_BASE,
+                        pkg.applicationInfo);
+            } catch (RemoteException | NullPointerException e) {
+                Log.e(TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
+            }
         }
         // Fall back to previous behaviour.
-        return pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.Q;
+        return pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.Q;
     }
 
     @Override
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index ccfa184..1e88ce7 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -312,7 +312,7 @@
      */
     public boolean supportsSwitchToByUser() {
         // Hide the system user when it does not represent a human user.
-        boolean hideSystemUser = UserManager.isSplitSystemUser();
+        boolean hideSystemUser = UserManager.isHeadlessSystemUserMode();
         return (!hideSystemUser || id != UserHandle.USER_SYSTEM) && supportsSwitchTo();
     }
 
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
deleted file mode 100644
index f072167..0000000
--- a/core/java/android/content/pm/VerificationParams.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2012 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.content.pm;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents verification parameters used to verify packages to be installed.
- *
- * @deprecated callers should migrate to {@link PackageInstaller}.
- * @hide
- */
-@Deprecated
-public class VerificationParams implements Parcelable {
-    /** A constant used to indicate that a uid value is not present. */
-    public static final int NO_UID = -1;
-
-    /** What we print out first when toString() is called. */
-    private static final String TO_STRING_PREFIX = "VerificationParams{";
-
-    /** The location of the supplementary verification file. */
-    private final Uri mVerificationURI;
-
-    /** URI referencing where the package was downloaded from. */
-    private final Uri mOriginatingURI;
-
-    /** HTTP referrer URI associated with the originatingURI. */
-    private final Uri mReferrer;
-
-    /** UID of the application that the install request originated from. */
-    private final int mOriginatingUid;
-
-    /** UID of application requesting the install */
-    private int mInstallerUid;
-
-    /**
-     * Creates verification specifications for installing with application verification.
-     *
-     * @param verificationURI The location of the supplementary verification
-     *            file. This can be a 'file:' or a 'content:' URI. May be {@code null}.
-     * @param originatingURI URI referencing where the package was downloaded
-     *            from. May be {@code null}.
-     * @param referrer HTTP referrer URI associated with the originatingURI.
-     *            May be {@code null}.
-     * @param originatingUid UID of the application that the install request originated
-     *            from, or NO_UID if not present
-     */
-    public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
-            int originatingUid) {
-        mVerificationURI = verificationURI;
-        mOriginatingURI = originatingURI;
-        mReferrer = referrer;
-        mOriginatingUid = originatingUid;
-        mInstallerUid = NO_UID;
-    }
-
-    public Uri getVerificationURI() {
-        return mVerificationURI;
-    }
-
-    public Uri getOriginatingURI() {
-        return mOriginatingURI;
-    }
-
-    public Uri getReferrer() {
-        return mReferrer;
-    }
-
-    /** return NO_UID if not available */
-    public int getOriginatingUid() {
-        return mOriginatingUid;
-    }
-
-    /** @return NO_UID when not set */
-    public int getInstallerUid() {
-        return mInstallerUid;
-    }
-
-    public void setInstallerUid(int uid) {
-        mInstallerUid = uid;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-
-        if (!(o instanceof VerificationParams)) {
-            return false;
-        }
-
-        final VerificationParams other = (VerificationParams) o;
-
-        if (mVerificationURI == null) {
-            if (other.mVerificationURI != null) {
-                return false;
-            }
-        } else if (!mVerificationURI.equals(other.mVerificationURI)) {
-            return false;
-        }
-
-        if (mOriginatingURI == null) {
-            if (other.mOriginatingURI != null) {
-                return false;
-            }
-        } else if (!mOriginatingURI.equals(other.mOriginatingURI)) {
-            return false;
-        }
-
-        if (mReferrer == null) {
-            if (other.mReferrer != null) {
-                return false;
-            }
-        } else if (!mReferrer.equals(other.mReferrer)) {
-            return false;
-        }
-
-        if (mOriginatingUid != other.mOriginatingUid) {
-            return false;
-        }
-
-        if (mInstallerUid != other.mInstallerUid) {
-            return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 3;
-
-        hash += 5 * (mVerificationURI == null ? 1 : mVerificationURI.hashCode());
-        hash += 7 * (mOriginatingURI == null ? 1 : mOriginatingURI.hashCode());
-        hash += 11 * (mReferrer == null ? 1 : mReferrer.hashCode());
-        hash += 13 * mOriginatingUid;
-        hash += 17 * mInstallerUid;
-
-        return hash;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
-
-        sb.append("mVerificationURI=");
-        sb.append(mVerificationURI.toString());
-        sb.append(",mOriginatingURI=");
-        sb.append(mOriginatingURI.toString());
-        sb.append(",mReferrer=");
-        sb.append(mReferrer.toString());
-        sb.append(",mOriginatingUid=");
-        sb.append(mOriginatingUid);
-        sb.append(",mInstallerUid=");
-        sb.append(mInstallerUid);
-        sb.append('}');
-
-        return sb.toString();
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mVerificationURI, 0);
-        dest.writeParcelable(mOriginatingURI, 0);
-        dest.writeParcelable(mReferrer, 0);
-        dest.writeInt(mOriginatingUid);
-        dest.writeInt(mInstallerUid);
-    }
-
-
-    private VerificationParams(Parcel source) {
-        mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
-        mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
-        mReferrer = source.readParcelable(Uri.class.getClassLoader());
-        mOriginatingUid = source.readInt();
-        mInstallerUid = source.readInt();
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<VerificationParams> CREATOR =
-            new Parcelable.Creator<VerificationParams>() {
-        public VerificationParams createFromParcel(Parcel source) {
-                return new VerificationParams(source);
-        }
-
-        public VerificationParams[] newArray(int size) {
-            return new VerificationParams[size];
-        }
-    };
-}
diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
index 0ec812f..698876b 100644
--- a/core/java/android/hardware/biometrics/BiometricAuthenticator.java
+++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
@@ -36,23 +36,30 @@
      * @hide
      */
     int TYPE_NONE = 0;
+
+    /**
+     * Constant representing credential (PIN, pattern, or password).
+     * @hide
+     */
+    int TYPE_CREDENTIAL = 1 << 0;
+
     /**
      * Constant representing fingerprint.
      * @hide
      */
-    int TYPE_FINGERPRINT = 1 << 0;
+    int TYPE_FINGERPRINT = 1 << 1;
 
     /**
      * Constant representing iris.
      * @hide
      */
-    int TYPE_IRIS = 1 << 1;
+    int TYPE_IRIS = 1 << 2;
 
     /**
      * Constant representing face.
      * @hide
      */
-    int TYPE_FACE = 1 << 2;
+    int TYPE_FACE = 1 << 3;
 
     /**
      * Container for biometric data
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 27c04b4..c8bf570 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -134,6 +134,13 @@
     int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
 
     /**
+     * This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
+     * because the authentication attempt was unsuccessful.
+     * @hide
+     */
+    int BIOMETRIC_PAUSED_REJECTED = 100;
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index cbe8a05..9d427c8 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -137,7 +137,7 @@
     public boolean hasEnrolledBiometrics(int userId) {
         if (mService != null) {
             try {
-                return mService.hasEnrolledBiometrics(userId);
+                return mService.hasEnrolledBiometrics(userId, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.w(TAG, "Remote exception in hasEnrolledBiometrics(): " + e);
                 return false;
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index cf86e251..9c51b52 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -26,6 +26,8 @@
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.CancellationSignal;
@@ -339,9 +341,23 @@
         }
 
         @Override
-        public void onError(int error, String message) throws RemoteException {
+        public void onError(int modality, int error, int vendorCode) throws RemoteException {
             mExecutor.execute(() -> {
-                mAuthenticationCallback.onAuthenticationError(error, message);
+                String errorMessage;
+                switch (modality) {
+                    case TYPE_FACE:
+                        errorMessage = FaceManager.getErrorString(mContext, error, vendorCode);
+                        break;
+
+                    case TYPE_FINGERPRINT:
+                        errorMessage = FingerprintManager.getErrorString(mContext, error,
+                                vendorCode);
+                        break;
+
+                    default:
+                        errorMessage = "";
+                }
+                mAuthenticationCallback.onAuthenticationError(error, errorMessage);
             });
         }
 
diff --git a/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
new file mode 100644
index 0000000..987d197
--- /dev/null
+++ b/core/java/android/hardware/biometrics/IBiometricAuthenticator.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.hardware.biometrics;
+
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
+import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.face.IFaceServiceReceiver;
+import android.hardware.face.Face;
+
+/**
+ * This interface encapsulates fingerprint, face, iris, etc. authenticators.
+ * Implementations of this interface are meant to be registered with BiometricService.
+ * @hide
+ */
+interface IBiometricAuthenticator {
+
+    // This method prepares the service to start authenticating, but doesn't start authentication.
+    // This is protected by the MANAGE_BIOMETRIC signature permission. This method should only be
+    // called from BiometricService. The additional uid, pid, userId arguments should be determined
+    // by BiometricService. To start authentication after the clients are ready, use
+    // startPreparedClient().
+    void prepareForAuthentication(boolean requireConfirmation, IBinder token, long sessionId,
+            int userId, IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName,
+            int cookie, int callingUid, int callingPid, int callingUserId);
+
+    // Starts authentication with the previously prepared client.
+    void startPreparedClient(int cookie);
+
+    // Same as above, with extra arguments.
+    void cancelAuthenticationFromService(IBinder token, String opPackageName,
+            int callingUid, int callingPid, int callingUserId, boolean fromClient);
+
+    // Determine if HAL is loaded and ready
+    boolean isHardwareDetected(String opPackageName);
+
+    // Determine if a user has at least one enrolled face
+    boolean hasEnrolledTemplates(int userId, String opPackageName);
+
+    // Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password)
+    void resetLockout(in byte [] token);
+
+    // Explicitly set the active user (for enrolling work profile)
+    void setActiveUser(int uid);
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index 6a3bf38..06336a5 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -19,6 +19,7 @@
 import android.os.Bundle;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricServiceReceiver;
+import android.hardware.biometrics.IBiometricAuthenticator;
 
 /**
  * Communication channel from BiometricPrompt and BiometricManager to BiometricService. The
@@ -40,7 +41,12 @@
     int canAuthenticate(String opPackageName, int userId);
 
     // Checks if any biometrics are enrolled.
-    boolean hasEnrolledBiometrics(int userId);
+    boolean hasEnrolledBiometrics(int userId, String opPackageName);
+
+    // Registers an authenticator (e.g. face, fingerprint, iris).
+    // Id must be unique, whereas strength and modality don't need to be.
+    // TODO(b/123321528): Turn strength and modality into enums.
+    void registerAuthenticator(int id, int strength, int modality, IBiometricAuthenticator authenticator);
 
     // Register callback for when keyguard biometric eligibility changes.
     void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback);
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
index 22ef33e..c960049 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
@@ -25,7 +25,7 @@
     // Noties that authentication failed.
     void onAuthenticationFailed();
     // Notify BiometricPrompt that an error has occurred.
-    void onError(int error, String message);
+    void onError(int modality, int error, int vendorCode);
     // Notifies that a biometric has been acquired.
     void onAcquired(int acquiredInfo, String message);
     // Notifies that the SystemUI dialog has been dismissed.
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
index 66b6e89..61310f3 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
@@ -31,7 +31,7 @@
     void onAuthenticationFailed();
     // Notify BiometricService than an error has occured. Forward to the correct receiver depending
     // on the cookie.
-    void onError(int cookie, int error, String message);
+    void onError(int cookie, int modality, int error, int vendorCode);
     // Notifies that a biometric has been acquired.
     void onAcquired(int acquiredInfo, String message);
     // Notifies that the SystemUI dialog has been dismissed.
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 12b285a..55ebe28 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -504,8 +504,7 @@
     public boolean isHardwareDetected() {
         if (mService != null) {
             try {
-                long deviceId = 0; /* TODO: plumb hardware id to FPMS */
-                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
+                return mService.isHardwareDetected(mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index b6a0afb..68a4aef 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -67,7 +67,7 @@
     List<Face> getEnrolledFaces(int userId, String opPackageName);
 
     // Determine if HAL is loaded and ready
-    boolean isHardwareDetected(long deviceId, String opPackageName);
+    boolean isHardwareDetected(String opPackageName);
 
     // Get a pre-enrollment authentication token
     long generateChallenge(IBinder token);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d0622c8..22f8590 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -691,8 +691,7 @@
     public boolean isHardwareDetected() {
         if (mService != null) {
             try {
-                long deviceId = 0; /* TODO: plumb hardware id to FPMS */
-                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
+                return mService.isHardwareDetected(mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index dd6b29d..1a7e128 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -71,7 +71,7 @@
     List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName);
 
     // Determine if HAL is loaded and ready
-    boolean isHardwareDetected(long deviceId, String opPackageName);
+    boolean isHardwareDetected(String opPackageName);
 
     // Get a pre-enrollment authentication token
     long preEnroll(IBinder token);
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index 160376b..eb5d0cb 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -58,8 +58,8 @@
      */
     private static final String VOICE_KEYPHRASE_META_DATA = "android.voice_enrollment";
     /**
-     * Activity Action: Show activity for managing the keyphrases for hotword detection.
-     * This needs to be defined by an activity that supports enrolling users for hotword/keyphrase
+     * Intent Action: for managing the keyphrases for hotword detection.
+     * This needs to be defined by a service that supports enrolling users for hotword/keyphrase
      * detection.
      */
     public static final String ACTION_MANAGE_VOICE_KEYPHRASES =
@@ -101,7 +101,7 @@
         // Find the apps that supports enrollment for hotword keyhphrases,
         // Pick a privileged app and obtain the information about the supported keyphrases
         // from its metadata.
-        List<ResolveInfo> ris = pm.queryIntentActivities(
+        List<ResolveInfo> ris = pm.queryIntentServices(
                 new Intent(ACTION_MANAGE_VOICE_KEYPHRASES), PackageManager.MATCH_DEFAULT_ONLY);
         if (ris == null || ris.isEmpty()) {
             // No application capable of enrolling for voice keyphrases is present.
@@ -116,11 +116,11 @@
         for (ResolveInfo ri : ris) {
             try {
                 ApplicationInfo ai = pm.getApplicationInfo(
-                        ri.activityInfo.packageName, PackageManager.GET_META_DATA);
+                        ri.serviceInfo.packageName, PackageManager.GET_META_DATA);
                 if ((ai.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) == 0) {
                     // The application isn't privileged (/system/priv-app).
                     // The enrollment application needs to be a privileged system app.
-                    Slog.w(TAG, ai.packageName + "is not a privileged system app");
+                    Slog.w(TAG, ai.packageName + " is not a privileged system app");
                     continue;
                 }
                 if (!Manifest.permission.MANAGE_VOICE_KEYPHRASES.equals(ai.permission)) {
@@ -137,7 +137,7 @@
                 }
             } catch (PackageManager.NameNotFoundException e) {
                 String error = "error parsing voice enrollment meta-data for "
-                        + ri.activityInfo.packageName;
+                        + ri.serviceInfo.packageName;
                 parseErrors.add(error + ": " + e);
                 Slog.w(TAG, error, e);
             }
@@ -290,7 +290,7 @@
     }
 
     /**
-     * Returns an intent to launch an activity that manages the given keyphrase
+     * Returns an intent to launch an service that manages the given keyphrase
      * for the locale.
      *
      * @param action The enrollment related action that this intent is supposed to perform.
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 11f4ffb..ee2e262 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -63,6 +63,8 @@
     private final boolean mHasAudioPlayback;
     private final boolean mHasAudioCapture;
     private final boolean mHasMidi;
+    private final boolean mHasVideoPlayback;
+    private final boolean mHasVideoCapture;
 
     /** All interfaces on the device. Initialized on first call to getInterfaceList */
     @UnsupportedAppUsage
@@ -77,7 +79,8 @@
             int protocol, @Nullable String manufacturerName, @Nullable String productName,
             @NonNull String version, @NonNull UsbConfiguration[] configurations,
             @NonNull IUsbSerialReader serialNumberReader,
-            boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi) {
+            boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi,
+            boolean hasVideoPlayback, boolean hasVideoCapture) {
         mName = Preconditions.checkNotNull(name);
         mVendorId = vendorId;
         mProductId = productId;
@@ -92,6 +95,8 @@
         mHasAudioPlayback = hasAudioPlayback;
         mHasAudioCapture = hasAudioCapture;
         mHasMidi = hasMidi;
+        mHasVideoPlayback = hasVideoPlayback;
+        mHasVideoCapture = hasVideoCapture;
 
         // Make sure the binder belongs to the system
         if (ActivityThread.isSystem()) {
@@ -236,6 +241,16 @@
         return mHasMidi;
     }
 
+    /** @hide */
+    public boolean getHasVideoPlayback() {
+        return mHasVideoPlayback;
+    }
+
+    /** @hide */
+    public boolean getHasVideoCapture() {
+        return mHasVideoCapture;
+    }
+
     /**
      * Returns the {@link UsbConfiguration} at the given index.
      *
@@ -316,6 +331,8 @@
                 + ", mHasAudioPlayback=" + mHasAudioPlayback
                 + ", mHasAudioCapture=" + mHasAudioCapture
                 + ", mHasMidi=" + mHasMidi
+                + ", mHasVideoCapture=" + mHasVideoCapture
+                + ", mHasVideoPlayback=" + mHasVideoPlayback
                 + ", mConfigurations=[");
         for (int i = 0; i < mConfigurations.length; i++) {
             builder.append("\n");
@@ -345,10 +362,12 @@
             boolean hasAudioPlayback = in.readInt() == 1;
             boolean hasAudioCapture = in.readInt() == 1;
             boolean hasMidi = in.readInt() == 1;
-
+            boolean hasVideoPlayback = in.readInt() == 1;
+            boolean hasVideoCapture = in.readInt() == 1;
             UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
                     manufacturerName, productName, version, configurations, serialNumberReader,
-                    hasAudioPlayback, hasAudioCapture, hasMidi);
+                    hasAudioPlayback, hasAudioCapture, hasMidi,
+                    hasVideoPlayback, hasVideoCapture);
 
             return device;
         }
@@ -377,6 +396,8 @@
         parcel.writeInt(mHasAudioPlayback ? 1 : 0);
         parcel.writeInt(mHasAudioCapture ? 1 : 0);
         parcel.writeInt(mHasMidi ? 1 : 0);
+        parcel.writeInt(mHasVideoPlayback ? 1 : 0);
+        parcel.writeInt(mHasVideoCapture ? 1 : 0);
     }
 
     public static int getDeviceId(String name) {
@@ -407,6 +428,8 @@
         private final boolean mHasAudioPlayback;
         private final boolean mHasAudioCapture;
         private final boolean mHasMidi;
+        private final boolean mHasVideoPlayback;
+        private final boolean mHasVideoCapture;
 
         // Temporary storage for serial number. Serial number reader need to be wrapped in a
         // IUsbSerialReader as they might be used as PII.
@@ -416,7 +439,8 @@
                 int protocol, @Nullable String manufacturerName, @Nullable String productName,
                 @NonNull String version, @NonNull UsbConfiguration[] configurations,
                 @Nullable String serialNumber,
-                boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi) {
+                boolean hasAudioPlayback, boolean hasAudioCapture, boolean hasMidi,
+                boolean hasVideoPlayback, boolean hasVideoCapture) {
             mName = Preconditions.checkNotNull(name);
             mVendorId = vendorId;
             mProductId = productId;
@@ -431,6 +455,8 @@
             mHasAudioPlayback = hasAudioPlayback;
             mHasAudioCapture = hasAudioCapture;
             mHasMidi = hasMidi;
+            mHasVideoPlayback = hasVideoPlayback;
+            mHasVideoCapture = hasVideoCapture;
         }
 
         /**
@@ -443,7 +469,8 @@
         public UsbDevice build(@NonNull IUsbSerialReader serialReader) {
             return new UsbDevice(mName, mVendorId, mProductId, mClass, mSubclass, mProtocol,
                     mManufacturerName, mProductName, mVersion, mConfigurations, serialReader,
-                    mHasAudioPlayback, mHasAudioCapture, mHasMidi);
+                    mHasAudioPlayback, mHasAudioCapture, mHasMidi,
+                    mHasVideoPlayback, mHasVideoCapture);
         }
     }
 }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 83391f3..43842c5 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -94,6 +94,7 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
 
 /**
  * InputMethodService provides a standard implementation of an InputMethod,
@@ -434,6 +435,7 @@
     final int[] mTmpLocation = new int[2];
 
     final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = info -> {
+        onComputeInsets(mTmpInsets);
         if (isExtractViewShown()) {
             // In true fullscreen mode, we just say the window isn't covering
             // any content so we don't impact whatever is behind.
@@ -442,12 +444,15 @@
             info.touchableRegion.setEmpty();
             info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
         } else {
-            onComputeInsets(mTmpInsets);
             info.contentInsets.top = mTmpInsets.contentTopInsets;
             info.visibleInsets.top = mTmpInsets.visibleTopInsets;
             info.touchableRegion.set(mTmpInsets.touchableRegion);
             info.setTouchableInsets(mTmpInsets.touchableInsets);
         }
+
+        if (mInputFrame != null) {
+            setImeExclusionRect(mTmpInsets.visibleTopInsets);
+        }
     };
 
     final View.OnClickListener mActionClickListener = v -> {
@@ -672,6 +677,14 @@
         mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition);
     }
 
+    /** Set region of the keyboard to be avoided from back gesture */
+    private void setImeExclusionRect(int visibleTopInsets) {
+        View inputFrameRootView = mInputFrame.getRootView();
+        Rect r = new Rect(0, visibleTopInsets, inputFrameRootView.getWidth(),
+                inputFrameRootView.getHeight());
+        inputFrameRootView.setSystemGestureExclusionRects(Collections.singletonList(r));
+    }
+
     /**
      * Concrete implementation of
      * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5c65238..cfa3934 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -473,6 +473,14 @@
     public static final int TETHERING_BLUETOOTH = 2;
 
     /**
+     * Wifi P2p tethering type.
+     * Wifi P2p tethering is set through events automatically, and don't
+     * need to start from #startTethering(int, boolean, OnStartTetheringCallback).
+     * @hide
+     */
+    public static final int TETHERING_WIFI_P2P = 3;
+
+    /**
      * Extra used for communicating with the TetherService. Includes the type of tethering to
      * enable if any.
      * @hide
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 2cf2a65..8729514 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -416,7 +416,6 @@
      * @param mask MacAddress representing the mask to use during comparison.
      * @return true if this MAC Address matches the given range.
      *
-     * @hide
      */
     public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
         Preconditions.checkNotNull(baseAddress);
@@ -430,7 +429,6 @@
      * IPv6 address per RFC 4862.
      *
      * @return A link-local Inet6Address constructed from the MAC address.
-     * @hide
      */
     public @Nullable Inet6Address getLinkLocalIpv6FromEui48Mac() {
         byte[] macEui48Bytes = toByteArray();
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 3e325b7..e3259ff 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -57,6 +57,9 @@
     private static final String TAG = "NetworkCapabilities";
     private static final int INVALID_UID = -1;
 
+    // Set to true when private DNS is broken.
+    private boolean mPrivateDnsBroken;
+
     /**
      * @hide
      */
@@ -86,6 +89,7 @@
         mUids = null;
         mEstablishingVpnAppUid = INVALID_UID;
         mSSID = null;
+        mPrivateDnsBroken = false;
     }
 
     /**
@@ -104,6 +108,7 @@
         mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
         mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
         mSSID = nc.mSSID;
+        mPrivateDnsBroken = nc.mPrivateDnsBroken;
     }
 
     /**
@@ -557,6 +562,9 @@
         }
         if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth";
         if (hasSignalStrength()) return "signalStrength";
+        if (isPrivateDnsBroken()) {
+            return "privateDnsBroken";
+        }
         return null;
     }
 
@@ -1443,7 +1451,8 @@
                 && equalsSpecifier(that)
                 && equalsTransportInfo(that)
                 && equalsUids(that)
-                && equalsSSID(that));
+                && equalsSSID(that)
+                && equalsPrivateDnsBroken(that));
     }
 
     @Override
@@ -1460,7 +1469,8 @@
                 + (mSignalStrength * 29)
                 + Objects.hashCode(mUids) * 31
                 + Objects.hashCode(mSSID) * 37
-                + Objects.hashCode(mTransportInfo) * 41;
+                + Objects.hashCode(mTransportInfo) * 41
+                + Objects.hashCode(mPrivateDnsBroken) * 43;
     }
 
     @Override
@@ -1479,6 +1489,7 @@
         dest.writeInt(mSignalStrength);
         dest.writeArraySet(mUids);
         dest.writeString(mSSID);
+        dest.writeBoolean(mPrivateDnsBroken);
     }
 
     public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1498,6 +1509,7 @@
                 netCap.mUids = (ArraySet<UidRange>) in.readArraySet(
                         null /* ClassLoader, null for default */);
                 netCap.mSSID = in.readString();
+                netCap.mPrivateDnsBroken = in.readBoolean();
                 return netCap;
             }
             @Override
@@ -1555,6 +1567,10 @@
             sb.append(" SSID: ").append(mSSID);
         }
 
+        if (mPrivateDnsBroken) {
+            sb.append(" Private DNS is broken");
+        }
+
         sb.append("]");
         return sb.toString();
     }
@@ -1706,4 +1722,28 @@
     public boolean isMetered() {
         return !hasCapability(NET_CAPABILITY_NOT_METERED);
     }
+
+    /**
+     * Check if private dns is broken.
+     *
+     * @return {@code true} if {@code mPrivateDnsBroken} is set when private DNS is broken.
+     * @hide
+     */
+    public boolean isPrivateDnsBroken() {
+        return mPrivateDnsBroken;
+    }
+
+    /**
+     * Set mPrivateDnsBroken to true when private dns is broken.
+     *
+     * @param broken the status of private DNS to be set.
+     * @hide
+     */
+    public void setPrivateDnsBroken(boolean broken) {
+        mPrivateDnsBroken = broken;
+    }
+
+    private boolean equalsPrivateDnsBroken(NetworkCapabilities nc) {
+        return mPrivateDnsBroken == nc.mPrivateDnsBroken;
+    }
 }
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 9ba3bd9..4ad52d5 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -77,6 +77,12 @@
      */
     public boolean skip464xlat;
 
+    /**
+     * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network.
+     * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode.
+     */
+    public boolean hasShownBroken;
+
     public NetworkMisc() {
     }
 
diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java
index 767c15c..9c999b2 100644
--- a/core/java/android/os/ConfigUpdate.java
+++ b/core/java/android/os/ConfigUpdate.java
@@ -113,6 +113,21 @@
     public static final String ACTION_UPDATE_CARRIER_ID_DB
             = "android.os.action.UPDATE_CARRIER_ID_DB";
 
+    /**
+    * Broadcast intent action indicating that the updated emergency number database is available.
+    * <p>Extra: "VERSION" the numeric version of the new data. Devices should only install if the
+    * update version is newer than the current one.
+    * <p>Extra: "REQUIRED_HASH" the hash of the current update data.
+    * <p>Input: {@link android.content.Intent#getData} is URI of downloaded emergency number file.
+    * Devices should pick up the downloaded file and persist to the database
+    * {@code com.android.internal.telephony.emergency.EmergencyNumberTracker}.
+    *
+    * @hide
+    */
+    @SystemApi
+    public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB =
+            "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
+
     private ConfigUpdate() {
     }
 }
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 6d5fe53b..a92237b 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -55,6 +55,7 @@
     private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
     private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT";
     private static final String ENV_SYSTEM_EXT_ROOT = "SYSTEM_EXT_ROOT";
+    private static final String ENV_APEX_ROOT = "APEX_ROOT";
 
     /** {@hide} */
     public static final String DIR_ANDROID = "Android";
@@ -78,7 +79,9 @@
     private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
     private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
     private static final File DIR_SYSTEM_EXT_ROOT = getDirectory(ENV_SYSTEM_EXT_ROOT,
-                                                           "/system_ext");
+            "/system_ext");
+    private static final File DIR_APEX_ROOT = getDirectory(ENV_APEX_ROOT,
+            "/apex");
 
     @UnsupportedAppUsage
     private static UserEnvironment sCurrentUser;
@@ -248,6 +251,16 @@
     }
 
     /**
+     * Return root directory of the apex mount point, where all the apex modules are made available
+     * to the rest of the system.
+     *
+     * @hide
+     */
+    public static @NonNull File getApexDirectory() {
+        return DIR_APEX_ROOT;
+    }
+
+    /**
      * Return the system directory for a user. This is for use by system
      * services to store files relating to the user. This directory will be
      * automatically deleted when the user is removed.
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index c30491a..e8cc73f 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -18,6 +18,7 @@
 package android.os;
 
 import android.os.Bundle;
+import android.os.IUserRestrictionsListener;
 import android.os.PersistableBundle;
 import android.os.UserManager;
 import android.content.pm.UserInfo;
@@ -75,6 +76,8 @@
     boolean hasBaseUserRestriction(String restrictionKey, int userHandle);
     boolean hasUserRestriction(in String restrictionKey, int userHandle);
     boolean hasUserRestrictionOnAnyUser(in String restrictionKey);
+    boolean isSettingRestrictedForUser(in String setting, int userId, in String value, int callingUid);
+    void addUserRestrictionsListener(IUserRestrictionsListener listener);
     void setUserRestriction(String key, boolean value, int userHandle);
     void setApplicationRestrictions(in String packageName, in Bundle restrictions,
             int userHandle);
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/core/java/android/os/IUserRestrictionsListener.aidl
similarity index 67%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to core/java/android/os/IUserRestrictionsListener.aidl
index d2ec357..e7d027f 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/core/java/android/os/IUserRestrictionsListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,13 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package android.os;
 
-parcelable TimeSignal;
\ No newline at end of file
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+oneway interface IUserRestrictionsListener {
+    void onUserRestrictionsChanged(int userId, in Bundle newRestrictions, in Bundle prevRestrictions);
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 3296f11..71b94ed 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1748,8 +1748,30 @@
         }
     }
 
-    /** {@hide} */
-    public boolean isUserUnlockingOrUnlocked(UserHandle user) {
+    /**
+     * Return whether the provided user is already running in an
+     * "unlocked" state or in the process of unlocking.
+     * <p>
+     * On devices with direct boot, a user is unlocked only after they've
+     * entered their credentials (such as a lock pattern or PIN). On devices
+     * without direct boot, a user is unlocked as soon as it starts.
+     * <p>
+     * When a user is locked, only device-protected data storage is available.
+     * When a user is unlocked, both device-protected and credential-protected
+     * private app data storage is available.
+     *
+     * <p>Requires {@code android.permission.MANAGE_USERS} or
+     * {@code android.permission.INTERACT_ACROSS_USERS}, otherwise specified {@link UserHandle user}
+     * must be the calling user or a profile associated with it.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            Manifest.permission.MANAGE_USERS,
+            Manifest.permission.INTERACT_ACROSS_USERS
+    })
+    public boolean isUserUnlockingOrUnlocked(@NonNull UserHandle user) {
         return isUserUnlockingOrUnlocked(user.getIdentifier());
     }
 
@@ -1986,6 +2008,38 @@
     }
 
     /**
+     * @hide
+     *
+     * Checks whether changing the given setting to the given value is prohibited
+     * by the corresponding user restriction in the given user.
+     *
+     * May only be called by the OS itself.
+     *
+     * @return {@code true} if the change is prohibited, {@code false} if the change is allowed.
+     */
+    public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
+            String value, int callingUid) {
+        try {
+            return mService.isSettingRestrictedForUser(setting, userId, value, callingUid);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
+     * Register a binder callback for user restrictions changes.
+     * May only be called by the OS itself.
+     */
+    public void addUserRestrictionsListener(final IUserRestrictionsListener listener) {
+        try {
+            mService.addUserRestrictionsListener(listener);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Return the serial number for a user.  This is a device-unique
      * number assigned to that user; if the user is deleted and then a new
      * user created, the new users will not be given the same serial number.
@@ -2536,6 +2590,22 @@
     }
 
     /**
+     * Checks if the 2 provided user handles belong to the same profile group.
+     *
+     * @param user one of the two user handles to check.
+     * @param otherUser one of the two user handles to check.
+     * @return true if the two users are in the same profile group.
+     *
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    public boolean isSameProfileGroup(@NonNull UserHandle user, @NonNull UserHandle otherUser) {
+        return isSameProfileGroup(user.getIdentifier(), otherUser.getIdentifier());
+    }
+
+    /**
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param userId one of the two user ids to check.
      * @param otherUserId one of the two user ids to check.
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index 77fd946..0e00d5e 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -104,16 +104,17 @@
      * Start DynamicSystem installation. This call may take an unbounded amount of time. The caller
      * may use another thread to call the getStartProgress() to get the progress.
      *
-     * @param systemSize system size in bytes
-     * @param userdataSize userdata size in bytes
+     * @param name The DSU partition name
+     * @param size Size of the DSU image in bytes
+     * @param readOnly True if the partition is read only, e.g. system.
      * @return {@code true} if the call succeeds. {@code false} either the device does not contain
      *     enough space or a DynamicSystem is currently in use where the {@link #isInUse} would be
      *     true.
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
-    public Session startInstallation(long systemSize, long userdataSize) {
+    public Session startInstallation(String name, long size, boolean readOnly) {
         try {
-            if (mService.startInstallation(systemSize, userdataSize)) {
+            if (mService.startInstallation(name, size, readOnly)) {
                 return new Session();
             } else {
                 return null;
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index a6de170..75f6785 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -24,11 +24,12 @@
      * Start DynamicSystem installation. This call may take 60~90 seconds. The caller
      * may use another thread to call the getStartProgress() to get the progress.
      *
-     * @param systemSize system size in bytes
-     * @param userdataSize userdata size in bytes
+     * @param name The DSU partition name
+     * @param size Size of the DSU image in bytes
+     * @param readOnly True if this partition is readOnly
      * @return true if the call succeeds
      */
-    boolean startInstallation(long systemSize, long userdataSize);
+    boolean startInstallation(@utf8InCpp String name, long size, boolean readOnly);
 
     /**
      * Query the progress of the current installation operation. This can be called while
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 0973a64..1643a21 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -38,11 +38,11 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telephony.CallerInfo;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.util.Log;
 
-import android.telephony.CallerInfo;
 import com.android.internal.telephony.PhoneConstants;
 
 import java.util.List;
@@ -234,6 +234,9 @@
         /** Call was on RTT at some point */
         public static final int FEATURES_RTT = 1 << 5;
 
+        /** Call was VoLTE */
+        public static final int FEATURES_VOLTE = 1 << 6;
+
         /**
          * The phone number as the user entered it.
          * <P>Type: TEXT</P>
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index e456c8a..8b8afd5 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -338,6 +338,15 @@
     public static final String NAMESPACE_PRIVACY = "privacy";
 
     /**
+     * Permission related properties definitions.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final String NAMESPACE_PERMISSIONS = "permissions";
+
+    /**
      * Interface for accessing keys belonging to {@link #NAMESPACE_WINDOW_MANAGER}.
      * @hide
      */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 065ee0b..cff99f3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7319,6 +7319,19 @@
         public static final String SILENCE_CALL_TOUCH_COUNT = "silence_call_touch_count";
 
         /**
+         * Number of successful "Motion Sense" tap gestures to pause media.
+         * @hide
+         */
+        public static final String AWARE_TAP_PAUSE_GESTURE_COUNT = "aware_tap_pause_gesture_count";
+
+        /**
+         * Number of touch interactions to pause media when a "Motion Sense" gesture could
+         * have been used.
+         * @hide
+         */
+        public static final String AWARE_TAP_PAUSE_TOUCH_COUNT = "aware_tap_pause_touch_count";
+
+        /**
          * The current night mode that has been selected by the user.  Owned
          * and controlled by UiModeManagerService.  Constants are as per
          * UiModeManager.
@@ -8581,13 +8594,19 @@
         public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
 
         /**
-         * URI for the "wireless charging started" and "wired charging started" sound.
+         * URI for the "wireless charging started" sound.
          * @hide
          */
-        public static final String CHARGING_STARTED_SOUND =
+        public static final String WIRELESS_CHARGING_STARTED_SOUND =
                 "wireless_charging_started_sound";
 
         /**
+         * URI for "wired charging started" sound.
+         * @hide
+         */
+        public static final String CHARGING_STARTED_SOUND = "charging_started_sound";
+
+        /**
          * Whether to play a sound for charging events.
          * @deprecated Use {@link android.provider.Settings.Secure#CHARGING_SOUNDS_ENABLED} instead
          * @hide
@@ -10863,16 +10882,13 @@
          * App standby (app idle) specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          * <p>
-         * "idle_duration=5000,parole_interval=4500,screen_thresholds=0/0/60000/120000"
+         * "idle_duration=5000,prediction_timeout=4500,screen_thresholds=0/0/60000/120000"
          * <p>
          * All durations are in millis.
          * Array values are separated by forward slashes
          * The following keys are supported:
          *
          * <pre>
-         * parole_interval                  (long)
-         * parole_window                    (long)
-         * parole_duration                  (long)
          * screen_thresholds                (long[4])
          * elapsed_thresholds               (long[4])
          * strong_usage_duration            (long)
@@ -10883,17 +10899,12 @@
          * exempted_sync_duration           (long)
          * system_interaction_duration      (long)
          * initial_foreground_service_start_duration (long)
-         * stable_charging_threshold        (long)
-         *
-         * idle_duration        (long) // This is deprecated and used to circumvent b/26355386.
-         * idle_duration2       (long) // deprecated
-         * wallclock_threshold  (long) // deprecated
          * </pre>
          *
          * <p>
          * Type: string
          * @hide
-         * @see com.android.server.usage.UsageStatsService.SettingsObserver
+         * @see com.android.server.usage.AppStandbyController
          */
         public static final String APP_IDLE_CONSTANTS = "app_idle_constants";
 
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 94b9d05..48ba429 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -181,6 +181,23 @@
     public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;
 
     /**
+     * Type used when the {@link FillResponse} represents a debit card.
+     */
+    public static final int SAVE_DATA_TYPE_DEBIT_CARD = 0x20;
+
+    /**
+     * Type used when the {@link FillResponse} represents a payment card except for credit and
+     * debit cards.
+     */
+    public static final int SAVE_DATA_TYPE_PAYMENT_CARD = 0x40;
+
+    /**
+     * Type used when the {@link FillResponse} represents a card that does not a specified card or
+     * cannot identify what the card is for.
+     */
+    public static final int SAVE_DATA_TYPE_GENERIC_CARD = 0x80;
+
+    /**
      * Style for the negative button of the save UI to cancel the
      * save operation. In this case, the user tapping the negative
      * button signals that they would prefer to not save the filled
@@ -207,6 +224,30 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface NegativeButtonStyle{}
 
+    /**
+     * Style for the positive button of save UI to request the save operation.
+     * In this case, the user tapping the positive button signals that they
+     * agrees to save the filled content.
+     */
+    public static final int POSITIVE_BUTTON_STYLE_SAVE = 0;
+
+    /**
+     * Style for the positive button of save UI to have next action before the save operation.
+     * This could be useful if the filled content contains sensitive personally identifiable
+     * information and then requires user confirmation or verification. In this case, the user
+     * tapping the positive button signals that they would complete the next required action
+     * to save the filled content.
+     */
+    public static final int POSITIVE_BUTTON_STYLE_CONTINUE = 1;
+
+    /** @hide */
+    @IntDef(prefix = { "POSITIVE_BUTTON_STYLE_" }, value = {
+            POSITIVE_BUTTON_STYLE_SAVE,
+            POSITIVE_BUTTON_STYLE_CONTINUE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface PositiveButtonStyle{}
+
     /** @hide */
     @IntDef(flag = true, prefix = { "SAVE_DATA_TYPE_" }, value = {
             SAVE_DATA_TYPE_GENERIC,
@@ -214,7 +255,10 @@
             SAVE_DATA_TYPE_ADDRESS,
             SAVE_DATA_TYPE_CREDIT_CARD,
             SAVE_DATA_TYPE_USERNAME,
-            SAVE_DATA_TYPE_EMAIL_ADDRESS
+            SAVE_DATA_TYPE_EMAIL_ADDRESS,
+            SAVE_DATA_TYPE_DEBIT_CARD,
+            SAVE_DATA_TYPE_PAYMENT_CARD,
+            SAVE_DATA_TYPE_GENERIC_CARD
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface SaveDataType{}
@@ -266,6 +310,7 @@
 
     private final @SaveDataType int mType;
     private final @NegativeButtonStyle int mNegativeButtonStyle;
+    private final @PositiveButtonStyle int mPositiveButtonStyle;
     private final IntentSender mNegativeActionListener;
     private final AutofillId[] mRequiredIds;
     private final AutofillId[] mOptionalIds;
@@ -281,6 +326,7 @@
         mType = builder.mType;
         mNegativeButtonStyle = builder.mNegativeButtonStyle;
         mNegativeActionListener = builder.mNegativeActionListener;
+        mPositiveButtonStyle = builder.mPositiveButtonStyle;
         mRequiredIds = builder.mRequiredIds;
         mOptionalIds = builder.mOptionalIds;
         mDescription = builder.mDescription;
@@ -313,6 +359,11 @@
     }
 
     /** @hide */
+    public @PositiveButtonStyle int getPositiveActionStyle() {
+        return mPositiveButtonStyle;
+    }
+
+    /** @hide */
     public @Nullable AutofillId[] getRequiredIds() {
         return mRequiredIds;
     }
@@ -374,6 +425,7 @@
 
         private final @SaveDataType int mType;
         private @NegativeButtonStyle int mNegativeButtonStyle = NEGATIVE_BUTTON_STYLE_CANCEL;
+        private @PositiveButtonStyle int mPositiveButtonStyle = POSITIVE_BUTTON_STYLE_SAVE;
         private IntentSender mNegativeActionListener;
         private final AutofillId[] mRequiredIds;
         private AutofillId[] mOptionalIds;
@@ -394,8 +446,9 @@
          * can be any combination of {@link SaveInfo#SAVE_DATA_TYPE_GENERIC},
          * {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
          * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD},
-         * {@link SaveInfo#SAVE_DATA_TYPE_USERNAME}, or
-         * {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
+         * {@link SaveInfo#SAVE_DATA_TYPE_DEBIT_CARD}, {@link SaveInfo#SAVE_DATA_TYPE_PAYMENT_CARD},
+         * {@link SaveInfo#SAVE_DATA_TYPE_GENERIC_CARD}, {@link SaveInfo#SAVE_DATA_TYPE_USERNAME},
+         * or {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
          * @param requiredIds ids of all required views that will trigger a save request.
          *
          * <p>See {@link SaveInfo} for more info.
@@ -418,8 +471,9 @@
          * can be any combination of {@link SaveInfo#SAVE_DATA_TYPE_GENERIC},
          * {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
          * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD},
-         * {@link SaveInfo#SAVE_DATA_TYPE_USERNAME}, or
-         * {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
+         * {@link SaveInfo#SAVE_DATA_TYPE_DEBIT_CARD}, {@link SaveInfo#SAVE_DATA_TYPE_PAYMENT_CARD},
+         * {@link SaveInfo#SAVE_DATA_TYPE_GENERIC_CARD}, {@link SaveInfo#SAVE_DATA_TYPE_USERNAME},
+         * or {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
          *
          * <p>See {@link SaveInfo} for more info.
          */
@@ -523,6 +577,8 @@
         public @NonNull Builder setNegativeAction(@NegativeButtonStyle int style,
                 @Nullable IntentSender listener) {
             throwIfDestroyed();
+            Preconditions.checkArgumentInRange(style, NEGATIVE_BUTTON_STYLE_CANCEL,
+                    NEGATIVE_BUTTON_STYLE_REJECT, "style");
             if (style != NEGATIVE_BUTTON_STYLE_CANCEL
                     && style != NEGATIVE_BUTTON_STYLE_REJECT) {
                 throw new IllegalArgumentException("Invalid style: " + style);
@@ -533,6 +589,33 @@
         }
 
         /**
+         * Sets the style for the positive save action.
+         *
+         * <p>This allows an autofill service to customize the style of the
+         * positive action in the save UI. Note that selecting the positive
+         * action regardless of its style would dismiss the save UI and calling
+         * into the {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback) save request}.
+         * The service should take the next action if selecting style
+         * {@link #POSITIVE_BUTTON_STYLE_CONTINUE}. The default style is
+         * {@link #POSITIVE_BUTTON_STYLE_SAVE}
+         *
+         * @param style The action style.
+         * @return This builder.
+         *
+         * @see #POSITIVE_BUTTON_STYLE_SAVE
+         * @see #POSITIVE_BUTTON_STYLE_CONTINUE
+         *
+         * @throws IllegalArgumentException If the style is invalid
+         */
+        public @NonNull Builder setPositiveAction(@PositiveButtonStyle int style) {
+            throwIfDestroyed();
+            Preconditions.checkArgumentInRange(style, POSITIVE_BUTTON_STYLE_SAVE,
+                    POSITIVE_BUTTON_STYLE_CONTINUE, "style");
+            mPositiveButtonStyle = style;
+            return this;
+        }
+
+        /**
          * Sets an object used to validate the user input - if the input is not valid, the
          * autofill save UI is not shown.
          *
@@ -717,8 +800,10 @@
         final StringBuilder builder = new StringBuilder("SaveInfo: [type=")
                 .append(DebugUtils.flagsToString(SaveInfo.class, "SAVE_DATA_TYPE_", mType))
                 .append(", requiredIds=").append(Arrays.toString(mRequiredIds))
-                .append(", style=").append(DebugUtils.flagsToString(SaveInfo.class,
-                        "NEGATIVE_BUTTON_STYLE_", mNegativeButtonStyle));
+                .append(", negative style=").append(DebugUtils.flagsToString(SaveInfo.class,
+                        "NEGATIVE_BUTTON_STYLE_", mNegativeButtonStyle))
+                .append(", positive style=").append(DebugUtils.flagsToString(SaveInfo.class,
+                        "POSITIVE_BUTTON_STYLE_", mPositiveButtonStyle));
         if (mOptionalIds != null) {
             builder.append(", optionalIds=").append(Arrays.toString(mOptionalIds));
         }
@@ -763,6 +848,7 @@
         parcel.writeParcelableArray(mOptionalIds, flags);
         parcel.writeInt(mNegativeButtonStyle);
         parcel.writeParcelable(mNegativeActionListener, flags);
+        parcel.writeInt(mPositiveButtonStyle);
         parcel.writeCharSequence(mDescription);
         parcel.writeParcelable(mCustomDescription, flags);
         parcel.writeParcelable(mValidator, flags);
@@ -794,6 +880,7 @@
             }
 
             builder.setNegativeAction(parcel.readInt(), parcel.readParcelable(null));
+            builder.setPositiveAction(parcel.readInt());
             builder.setDescription(parcel.readCharSequence());
             final CustomDescription customDescripton = parcel.readParcelable(null);
             if (customDescripton != null) {
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 9184d6d..eefc1b7 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -22,7 +22,7 @@
 import android.os.IBinder;
 import android.os.PersistableBundle;
 import android.os.ResultReceiver;
-import android.os.telephony.TelephonyRegistryManager;
+import android.telephony.TelephonyRegistryManager;
 import android.util.Log;
 
 /**
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index 8a9f689..12c2580 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -516,7 +516,7 @@
      * @see android.telephony.euicc.EuiccManager#eraseSubscriptions
      *
      * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase
-     * and use @link{onEraseSubscriptionsWithOptions} instead
+     * and use {@link #onEraseSubscriptionsWithOptions(int, int)} instead
      */
     @Deprecated
     public abstract int onEraseSubscriptions(int slotId);
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 94f6a50..cf56eae 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -20,7 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
-import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
@@ -446,7 +446,7 @@
 
     /**
      * Creates an intent to start the enrollment for the associated keyphrase.
-     * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+     * This intent must be invoked using {@link Context#startForegroundService(Intent)}.
      * Starting re-enrollment is only valid if the keyphrase is un-enrolled,
      * i.e. {@link #STATE_KEYPHRASE_UNENROLLED},
      * otherwise {@link #createReEnrollIntent()} should be preferred.
@@ -468,7 +468,7 @@
 
     /**
      * Creates an intent to start the un-enrollment for the associated keyphrase.
-     * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+     * This intent must be invoked using {@link Context#startForegroundService(Intent)}.
      * Starting re-enrollment is only valid if the keyphrase is already enrolled,
      * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error.
      *
@@ -489,7 +489,7 @@
 
     /**
      * Creates an intent to start the re-enrollment for the associated keyphrase.
-     * This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
+     * This intent must be invoked using {@link Context#startForegroundService(Intent)}.
      * Starting re-enrollment is only valid if the keyphrase is already enrolled,
      * i.e. {@link #STATE_KEYPHRASE_ENROLLED}, otherwise invoking this may result in an error.
      *
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
similarity index 99%
rename from telephony/java/android/telephony/PhoneStateListener.java
rename to core/java/android/telephony/PhoneStateListener.java
index 1ba0a41..a65c8fd 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -35,8 +35,8 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
+import com.android.internal.annotations.VisibleForTesting;
 
 import dalvik.system.VMRuntime;
 
diff --git a/core/java/android/os/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
similarity index 75%
rename from core/java/android/os/telephony/TelephonyRegistryManager.java
rename to core/java/android/telephony/TelephonyRegistryManager.java
index 1332331..64d6124 100644
--- a/core/java/android/os/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -13,12 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.os.telephony;
+package android.telephony;
 
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.content.Context;
 import android.net.LinkProperties;
 import android.net.NetworkCapabilities;
+import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.Annotation.ApnType;
@@ -40,8 +46,15 @@
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
 import android.telephony.ims.ImsReasonInfo;
+import android.util.Log;
+
 import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.IOnSubscriptionsChangedListener;
+
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update
@@ -58,9 +71,26 @@
 
     private static final String TAG = "TelephonyRegistryManager";
     private static ITelephonyRegistry sRegistry;
+    private final Context mContext;
+
+    /**
+     * A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and
+     * its callback IOnSubscriptionsChangedListener.
+     */
+    private final Map<SubscriptionManager.OnSubscriptionsChangedListener,
+                IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>();
+    /**
+     * A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and
+     * its callback IOnSubscriptionsChangedListener.
+     */
+    private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
+            IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap
+            = new HashMap<>();
+
 
     /** @hide **/
-    public TelephonyRegistryManager() {
+    public TelephonyRegistryManager(@NonNull Context context) {
+        mContext = context;
         if (sRegistry == null) {
             sRegistry = ITelephonyRegistry.Stub.asInterface(
                 ServiceManager.getService("telephony.registry"));
@@ -68,6 +98,113 @@
     }
 
     /**
+     * Register for changes to the list of active {@link SubscriptionInfo} records or to the
+     * individual records themselves. When a change occurs the onSubscriptionsChanged method of
+     * the listener will be invoked immediately if there has been a notification. The
+     * onSubscriptionChanged method will also be triggered once initially when calling this
+     * function.
+     *
+     * @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener}
+     *                 with onSubscriptionsChanged overridden.
+     * @param executor the executor that will execute callbacks.
+     */
+    public void addOnSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener,
+            @NonNull Executor executor) {
+        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
+            @Override
+            public void onSubscriptionsChanged () {
+                Log.d(TAG, "onSubscriptionsChangedListener callback received.");
+                executor.execute(() -> listener.onSubscriptionsChanged());
+            }
+        };
+        mSubscriptionChangedListenerMap.put(listener, callback);
+        try {
+            sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Unregister the {@link SubscriptionManager.OnSubscriptionsChangedListener}. This is not
+     * strictly necessary as the listener will automatically be unregistered if an attempt to
+     * invoke the listener fails.
+     *
+     * @param listener that is to be unregistered.
+     */
+    public void removeOnSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnSubscriptionsChangedListener listener) {
+        if (mSubscriptionChangedListenerMap.get(listener) == null) {
+            return;
+        }
+        try {
+            sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(),
+                    mSubscriptionChangedListenerMap.get(listener));
+            mSubscriptionChangedListenerMap.remove(listener);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Register for changes to the list of opportunistic subscription records or to the
+     * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged
+     * method of the listener will be invoked immediately if there has been a notification.
+     *
+     * @param listener an instance of
+     * {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} with
+     *                 onOpportunisticSubscriptionsChanged overridden.
+     * @param executor an Executor that will execute callbacks.
+     */
+    public void addOnOpportunisticSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener,
+            @NonNull Executor executor) {
+        /**
+         * The callback methods need to be called on the executor thread where
+         * this object was created.  If the binder did that for us it'd be nice.
+         */
+        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
+            @Override
+            public void onSubscriptionsChanged() {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    Log.d(TAG, "onOpportunisticSubscriptionsChanged callback received.");
+                    executor.execute(() -> listener.onOpportunisticSubscriptionsChanged());
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        };
+        mOpportunisticSubscriptionChangedListenerMap.put(listener, callback);
+        try {
+            sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(),
+                    callback);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Unregister the {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener}
+     * that is currently listening opportunistic subscriptions change. This is not strictly
+     * necessary as the listener will automatically be unregistered if an attempt to invoke the
+     * listener fails.
+     *
+     * @param listener that is to be unregistered.
+     */
+    public void removeOnOpportunisticSubscriptionsChangedListener(
+            @NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener) {
+        try {
+            sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(),
+                    mOpportunisticSubscriptionChangedListenerMap.get(listener));
+            mOpportunisticSubscriptionChangedListenerMap.remove(listener);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
      * Informs the system of an intentional upcoming carrier network change by a carrier app.
      * This call only used to allow the system to provide alternative UI while telephony is
      * performing an action that may result in intentional, temporary network lack of connectivity.
@@ -546,4 +683,15 @@
         }
     }
 
+    /**
+     * @param activeDataSubId
+     * @hide
+     */
+    public void notifyActiveDataSubIdChanged(int activeDataSubId) {
+        try {
+            sRegistry.notifyActiveDataSubIdChanged(activeDataSubId);
+        } catch (RemoteException ex) {
+
+        }
+    }
 }
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 1be57dd..b1fd4e5 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -41,14 +41,12 @@
     public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
     public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
     public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
-    public static final String USE_BUGREPORT_API = "settings_use_bugreport_api";
 
     private static final Map<String, String> DEFAULT_FLAGS;
 
     static {
         DEFAULT_FLAGS = new HashMap<>();
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
-        DEFAULT_FLAGS.put("settings_use_bugreport_api", "true");
         DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
         DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index d3b2c46..73e17a6 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -16,11 +16,16 @@
 
 package android.util;
 
+import android.os.Parcel;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
+import com.android.internal.util.Preconditions;
 
 import libcore.util.EmptyArray;
 
+import java.util.Arrays;
+
 /**
  * SparseArray mapping longs to Objects.  Unlike a normal array of Objects,
  * there can be gaps in the indices.  It is intended to be more memory efficient
@@ -442,4 +447,51 @@
         buffer.append('}');
         return buffer.toString();
     }
+
+    /**
+     * @hide
+     */
+    public static class StringParcelling implements
+            com.android.internal.util.Parcelling<LongSparseArray<String>> {
+        @Override
+        public void parcel(LongSparseArray<String> array, Parcel dest, int parcelFlags) {
+            if (array == null) {
+                dest.writeInt(-1);
+                return;
+            }
+
+            int size = array.mSize;
+
+            dest.writeInt(size);
+            dest.writeLongArray(array.mKeys);
+
+            dest.writeStringArray(Arrays.copyOfRange(array.mValues, 0, size, String[].class));
+        }
+
+        @Override
+        public LongSparseArray<String> unparcel(Parcel source) {
+            int size = source.readInt();
+            if (size == -1) {
+                return null;
+            }
+
+            LongSparseArray<String> array = new LongSparseArray<>(0);
+            array.mSize = size;
+            array.mKeys = source.createLongArray();
+            array.mValues = source.createStringArray();
+
+            // Make sure array is sane
+            Preconditions.checkArgument(array.mKeys.length >= size);
+            Preconditions.checkArgument(array.mValues.length >= size);
+
+            if (size > 0) {
+                long last = array.mKeys[0];
+                for (int i = 1; i < size; i++) {
+                    Preconditions.checkArgument(last < array.mKeys[i]);
+                }
+            }
+
+            return array;
+        }
+    }
 }
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index 7b7eea0..a0edd04 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -17,9 +17,11 @@
 package android.util;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Parcel;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
+import com.android.internal.util.Preconditions;
 
 import libcore.util.EmptyArray;
 
@@ -283,4 +285,49 @@
         buffer.append('}');
         return buffer.toString();
     }
+
+    /**
+     * @hide
+     */
+    public static class Parcelling implements
+            com.android.internal.util.Parcelling<LongSparseLongArray> {
+        @Override
+        public void parcel(LongSparseLongArray array, Parcel dest, int parcelFlags) {
+            if (array == null) {
+                dest.writeInt(-1);
+                return;
+            }
+
+            dest.writeInt(array.mSize);
+            dest.writeLongArray(array.mKeys);
+            dest.writeLongArray(array.mValues);
+        }
+
+        @Override
+        public LongSparseLongArray unparcel(Parcel source) {
+            int size = source.readInt();
+            if (size == -1) {
+                return null;
+            }
+
+            LongSparseLongArray array = new LongSparseLongArray(0);
+
+            array.mSize = size;
+            array.mKeys = source.createLongArray();
+            array.mValues = source.createLongArray();
+
+            // Make sure array is sane
+            Preconditions.checkArgument(array.mKeys.length >= size);
+            Preconditions.checkArgument(array.mValues.length >= size);
+
+            if (size > 0) {
+                long last = array.mKeys[0];
+                for (int i = 1; i < size; i++) {
+                    Preconditions.checkArgument(last < array.mKeys[i]);
+                }
+            }
+
+            return array;
+        }
+    }
 }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 35cfe9e..7f717a7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -306,6 +306,11 @@
     oneway void statusBarVisibilityChanged(int displayId, int visibility);
 
     /**
+     * Called by System UI to notify Window Manager to hide transient bars.
+     */
+    oneway void hideTransientBars(int displayId);
+
+    /**
     * When set to {@code true} the system bars will always be shown. This is true even if an app
     * requests to be fullscreen by setting the system ui visibility flags. The
     * functionality was added for the automotive case as a way to guarantee required content stays
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index e4deffa..0fb1c33 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -146,20 +146,11 @@
         }
         final Insets offset = Insets.subtract(mShownInsets, mPendingInsets);
         ArrayList<SurfaceParams> params = new ArrayList<>();
-        if (offset.left != 0) {
-            updateLeashesForSide(INSET_SIDE_LEFT, offset.left, mPendingInsets.left, params, state);
-        }
-        if (offset.top != 0) {
-            updateLeashesForSide(INSET_SIDE_TOP, offset.top, mPendingInsets.top, params, state);
-        }
-        if (offset.right != 0) {
-            updateLeashesForSide(INSET_SIDE_RIGHT, offset.right, mPendingInsets.right, params,
-                    state);
-        }
-        if (offset.bottom != 0) {
-            updateLeashesForSide(INSET_SIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params,
-                    state);
-        }
+        updateLeashesForSide(INSET_SIDE_LEFT, offset.left, mPendingInsets.left, params, state);
+        updateLeashesForSide(INSET_SIDE_TOP, offset.top, mPendingInsets.top, params, state);
+        updateLeashesForSide(INSET_SIDE_RIGHT, offset.right, mPendingInsets.right, params, state);
+        updateLeashesForSide(INSET_SIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params,
+                state);
         SyncRtSurfaceTransactionApplier applier = mTransactionApplierSupplier.get();
         applier.scheduleApply(params.toArray(new SurfaceParams[params.size()]));
         mCurrentInsets = mPendingInsets;
@@ -224,6 +215,9 @@
     private void updateLeashesForSide(@InsetSide int side, int offset, int inset,
             ArrayList<SurfaceParams> surfaceParams, InsetsState state) {
         ArraySet<InsetsSourceConsumer> items = mSideSourceMap.get(side);
+        if (items == null) {
+            return;
+        }
         // TODO: Implement behavior when inset spans over multiple types
         for (int i = items.size() - 1; i >= 0; i--) {
             final InsetsSourceConsumer consumer = items.valueAt(i);
@@ -274,9 +268,15 @@
             SparseSetArray<InsetsSourceConsumer> sideSourcesMap,
             SparseArray<InsetsSourceConsumer> consumers) {
         for (int i = typeSideMap.size() - 1; i >= 0; i--) {
-            int type = typeSideMap.keyAt(i);
-            int side = typeSideMap.valueAt(i);
-            sideSourcesMap.add(side, consumers.get(type));
+            final int type = typeSideMap.keyAt(i);
+            final int side = typeSideMap.valueAt(i);
+            final InsetsSourceConsumer consumer = consumers.get(type);
+            if (consumer == null) {
+                // If the types that we are controlling are less than the types that the system has,
+                // there can be some null consumers.
+                continue;
+            }
+            sideSourcesMap.add(side, consumer);
         }
     }
 }
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 5bb4f63..eca6dcb 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -67,9 +67,9 @@
      * Translation animation evaluator.
      */
     private static TypeEvaluator<Insets> sEvaluator = (fraction, startValue, endValue) -> Insets.of(
-            0,
+            (int) (startValue.left + fraction * (endValue.left - startValue.left)),
             (int) (startValue.top + fraction * (endValue.top - startValue.top)),
-            0,
+            (int) (startValue.right + fraction * (endValue.right - startValue.right)),
             (int) (startValue.bottom + fraction * (endValue.bottom - startValue.bottom)));
 
     /**
diff --git a/core/java/android/view/InsetsFlags.java b/core/java/android/view/InsetsFlags.java
index 276e80a..6e459b2 100644
--- a/core/java/android/view/InsetsFlags.java
+++ b/core/java/android/view/InsetsFlags.java
@@ -16,10 +16,18 @@
 
 package android.view;
 
+import static android.view.View.NAVIGATION_BAR_TRANSLUCENT;
+import static android.view.View.NAVIGATION_BAR_TRANSPARENT;
+import static android.view.View.STATUS_BAR_TRANSLUCENT;
+import static android.view.View.STATUS_BAR_TRANSPARENT;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
-import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_TOP_BAR;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE;
 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 
@@ -35,9 +43,13 @@
 
     @ViewDebug.ExportedProperty(flagMapping = {
             @ViewDebug.FlagToString(
-                    mask = APPEARANCE_OPAQUE_BARS,
-                    equals = APPEARANCE_OPAQUE_BARS,
-                    name = "OPAQUE_BARS"),
+                    mask = APPEARANCE_OPAQUE_TOP_BAR,
+                    equals = APPEARANCE_OPAQUE_TOP_BAR,
+                    name = "OPAQUE_TOP_BAR"),
+            @ViewDebug.FlagToString(
+                    mask = APPEARANCE_OPAQUE_SIDE_BARS,
+                    equals = APPEARANCE_OPAQUE_SIDE_BARS,
+                    name = "OPAQUE_SIDE_BARS"),
             @ViewDebug.FlagToString(
                     mask = APPEARANCE_LOW_PROFILE_BARS,
                     equals = APPEARANCE_LOW_PROFILE_BARS,
@@ -64,4 +76,44 @@
                     name = "SHOW_TRANSIENT_BARS_BY_SWIPE")
     })
     public @Behavior int behavior;
+
+    /**
+     * Converts system UI visibility to appearance.
+     *
+     * @param systemUiVisibility the system UI visibility to be converted.
+     * @return the outcome {@link Appearance}
+     */
+    public static @Appearance int getAppearance(int systemUiVisibility) {
+        int appearance = 0;
+        appearance |= convertFlag(systemUiVisibility, SYSTEM_UI_FLAG_LOW_PROFILE,
+                APPEARANCE_LOW_PROFILE_BARS);
+        appearance |= convertFlag(systemUiVisibility, SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+                APPEARANCE_LIGHT_TOP_BAR);
+        appearance |= convertFlag(systemUiVisibility, SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+                APPEARANCE_LIGHT_SIDE_BARS);
+        appearance |= convertNoFlag(systemUiVisibility,
+                STATUS_BAR_TRANSLUCENT | STATUS_BAR_TRANSPARENT, APPEARANCE_OPAQUE_TOP_BAR);
+        appearance |= convertNoFlag(systemUiVisibility,
+                NAVIGATION_BAR_TRANSLUCENT | NAVIGATION_BAR_TRANSPARENT,
+                APPEARANCE_OPAQUE_SIDE_BARS);
+        return appearance;
+    }
+
+    /**
+     * Converts the system UI visibility into an appearance flag if the given visibility contains
+     * the given system UI flag.
+     */
+    private static @Appearance int convertFlag(int systemUiVisibility, int systemUiFlag,
+            @Appearance int appearance) {
+        return (systemUiVisibility & systemUiFlag) != 0 ? appearance : 0;
+    }
+
+    /**
+     * Converts the system UI visibility into an appearance flag if the given visibility doesn't
+     * contains the given system UI flag.
+     */
+    private static @Appearance int convertNoFlag(int systemUiVisibility, int systemUiFlag,
+            @Appearance int appearance) {
+        return (systemUiVisibility & systemUiFlag) == 0 ? appearance : 0;
+    }
 }
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index a04c39b..99502a6 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -270,10 +270,23 @@
      *
      * @param type The {@link InternalInsetType} of the source to remove
      */
-    public void removeSource(int type) {
+    public void removeSource(@InternalInsetType int type) {
         mSources.remove(type);
     }
 
+    /**
+     * A shortcut for setting the visibility of the source.
+     *
+     * @param type The {@link InternalInsetType} of the source to set the visibility
+     * @param visible {@code true} for visible
+     */
+    public void setSourceVisible(@InternalInsetType int type, boolean visible) {
+        InsetsSource source = mSources.get(type);
+        if (source != null) {
+            source.setVisible(visible);
+        }
+    }
+
     public void set(InsetsState other) {
         set(other, false /* copySources */);
     }
@@ -357,6 +370,19 @@
         }
     }
 
+    public static boolean containsType(@InternalInsetType int[] types,
+            @InternalInsetType int type) {
+        if (types == null) {
+            return false;
+        }
+        for (int t : types) {
+            if (t == type) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "InsetsState");
         for (int i = mSources.size() - 1; i >= 0; i--) {
@@ -364,7 +390,7 @@
         }
     }
 
-    public static String typeToString(int type) {
+    public static String typeToString(@InternalInsetType int type) {
         switch (type) {
             case TYPE_TOP_BAR:
                 return "TYPE_TOP_BAR";
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index 2fd2e96..c5d45c3 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -16,7 +16,10 @@
 
 package android.view;
 
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.graphics.Canvas;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 
 /**
@@ -76,7 +79,7 @@
          *
          * @param holder The SurfaceHolder whose surface is being created.
          */
-        public void surfaceCreated(SurfaceHolder holder);
+        void surfaceCreated(@NonNull SurfaceHolder holder);
 
         /**
          * This is called immediately after any structural changes (format or
@@ -85,12 +88,12 @@
          * once, after {@link #surfaceCreated}.
          *
          * @param holder The SurfaceHolder whose surface has changed.
-         * @param format The new PixelFormat of the surface.
+         * @param format The new {@link PixelFormat} of the surface.
          * @param width The new width of the surface.
          * @param height The new height of the surface.
          */
-        public void surfaceChanged(SurfaceHolder holder, int format, int width,
-                int height);
+        void surfaceChanged(@NonNull SurfaceHolder holder, @PixelFormat.Format int format,
+                @IntRange(from = 0) int width, @IntRange(from = 0) int height);
 
         /**
          * This is called immediately before a surface is being destroyed. After
@@ -101,7 +104,7 @@
          *
          * @param holder The SurfaceHolder whose surface is being destroyed.
          */
-        public void surfaceDestroyed(SurfaceHolder holder);
+        void surfaceDestroyed(@NonNull SurfaceHolder holder);
     }
 
     /**
@@ -122,7 +125,7 @@
          *
          * @param holder The SurfaceHolder whose surface has changed.
          */
-        void surfaceRedrawNeeded(SurfaceHolder holder);
+        void surfaceRedrawNeeded(@NonNull SurfaceHolder holder);
 
         /**
          * An alternative to surfaceRedrawNeeded where it is not required to block
@@ -140,7 +143,8 @@
          * from any thread.
          *
          */
-        default void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable drawingFinished) {
+        default void surfaceRedrawNeededAsync(@NonNull SurfaceHolder holder,
+                @NonNull Runnable drawingFinished) {
             surfaceRedrawNeeded(holder);
             drawingFinished.run();
         }
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 396422e..b415319 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -35,33 +35,39 @@
 public interface WindowInsetsController {
 
     /**
-     * Makes system bars become opaque with solid dark background and light foreground.
+     * Makes the top bars become opaque with solid dark background and light foreground.
      * @hide
      */
-    int APPEARANCE_OPAQUE_BARS = 1;
+    int APPEARANCE_OPAQUE_TOP_BAR = 1;
+
+    /**
+     * Makes the side bars become opaque with solid dark background and light foreground.
+     * @hide
+     */
+    int APPEARANCE_OPAQUE_SIDE_BARS = 1 << 1;
 
     /**
      * Makes items on system bars become less noticeable without changing the layout of the bars.
      * @hide
      */
-    int APPEARANCE_LOW_PROFILE_BARS = 1 << 1;
+    int APPEARANCE_LOW_PROFILE_BARS = 1 << 2;
 
     /**
      * Changes the foreground color for the light top bar so that the items on the bar can be read
      * clearly.
      */
-    int APPEARANCE_LIGHT_TOP_BAR = 1 << 2;
+    int APPEARANCE_LIGHT_TOP_BAR = 1 << 3;
 
     /**
      * Changes the foreground color for the light side bars so that the items on the bar can be read
      * clearly.
      */
-    int APPEARANCE_LIGHT_SIDE_BARS = 1 << 3;
+    int APPEARANCE_LIGHT_SIDE_BARS = 1 << 4;
 
     /** Determines the appearance of system bars. */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = {APPEARANCE_OPAQUE_BARS, APPEARANCE_LOW_PROFILE_BARS,
-            APPEARANCE_LIGHT_TOP_BAR, APPEARANCE_LIGHT_SIDE_BARS})
+    @IntDef(flag = true, value = {APPEARANCE_OPAQUE_TOP_BAR, APPEARANCE_OPAQUE_SIDE_BARS,
+            APPEARANCE_LOW_PROFILE_BARS, APPEARANCE_LIGHT_TOP_BAR, APPEARANCE_LIGHT_SIDE_BARS})
     @interface Appearance {
     }
 
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 0817452..cc28840 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -707,10 +707,10 @@
         try {
             services = service.getEnabledAccessibilityServiceList(feedbackTypeFlags, userId);
             if (DEBUG) {
-                Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
+                Log.i(LOG_TAG, "Enabled AccessibilityServices " + services);
             }
         } catch (RemoteException re) {
-            Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
+            Log.e(LOG_TAG, "Error while obtaining the enabled AccessibilityServices. ", re);
         }
         if (mAccessibilityPolicy != null) {
             services = mAccessibilityPolicy.getEnabledAccessibilityServiceList(
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index cae1f38..3b82f18 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2505,9 +2505,7 @@
                         ri.noResourceId = true;
                         ri.icon = 0;
                     }
-                    ResolveInfoPresentationGetter getter = makePresentationGetter(ri);
-                    mCallerTargets.add(new DisplayResolveInfo(ii, ri,
-                            getter.getLabel(), getter.getSubLabel(), ii));
+                    mCallerTargets.add(new DisplayResolveInfo(ii, ri, ii));
                 }
             }
         }
@@ -2576,9 +2574,52 @@
             }
         }
 
+        /**
+         * Rather than fully sorting the input list, this sorting task will put the top k elements
+         * in the head of input list and fill the tail with other elements in undetermined order.
+         */
+        @Override
+        AsyncTask<List<ResolvedComponentInfo>,
+                Void,
+                List<ResolvedComponentInfo>> createSortingTask() {
+            return new AsyncTask<List<ResolvedComponentInfo>,
+                    Void,
+                    List<ResolvedComponentInfo>>() {
+                @Override
+                protected List<ResolvedComponentInfo> doInBackground(
+                        List<ResolvedComponentInfo>... params) {
+                    mResolverListController.topK(params[0],
+                            getMaxRankedTargets());
+                    return params[0];
+                }
+
+                @Override
+                protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
+                    processSortedList(sortedComponents);
+                    bindProfileView();
+                    notifyDataSetChanged();
+                }
+            };
+        }
+
         @Override
         public void onListRebuilt() {
-            updateAlphabeticalList();
+            if (getDisplayList() == null || getDisplayList().isEmpty()) {
+                notifyDataSetChanged();
+            } else {
+                new AsyncTask<Void, Void, Void>() {
+                    @Override
+                    protected Void doInBackground(Void... voids) {
+                        updateAlphabeticalList();
+                        return null;
+                    }
+
+                    @Override
+                    protected void onPostExecute(Void aVoid) {
+                        notifyDataSetChanged();
+                    }
+                }.execute();
+            }
 
             // don't support direct share on low ram devices
             if (ActivityManager.isLowRamDeviceStatic()) {
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 8f6c950..3ab0b0d2 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -31,25 +31,27 @@
     // be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
     // and not be reordered
     int checkOperation(int code, int uid, String packageName);
-    int noteOperation(int code, int uid, String packageName);
-    int startOperation(IBinder token, int code, int uid, String packageName,
+    int noteOperation(int code, int uid, String packageName, String featureId);
+    int startOperation(IBinder token, int code, int uid, String packageName, String featureId,
             boolean startIfModeDefault);
     @UnsupportedAppUsage
-    void finishOperation(IBinder token, int code, int uid, String packageName);
+    void finishOperation(IBinder token, int code, int uid, String packageName,
+            String featureId);
     void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
     void stopWatchingMode(IAppOpsCallback callback);
     IBinder getToken(IBinder clientToken);
     int permissionToOpCode(String permission);
     int checkAudioOperation(int code, int usage, int uid, String packageName);
     void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
-            String message);
+            String featureId, String message);
     boolean shouldCollectNotes(int opCode);
     void setCameraAudioRestriction(int mode);
     // End of methods also called by native code.
     // Any new method exposed to native must be added after the last one, do not reorder
 
-    int noteProxyOperation(int code, int proxyUid, String proxyPackageName,
-                int callingUid, String callingPackageName);
+    int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
+            String proxiedFeatureId, int proxyUid, String proxyPackageName,
+            String proxyFeatureId);
 
     // Remaining methods are only used in Java.
     int checkPackage(int uid, String packageName);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 068056f..74996e9 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1406,14 +1406,18 @@
 
     public final class DisplayResolveInfo implements TargetInfo {
         private final ResolveInfo mResolveInfo;
-        private final CharSequence mDisplayLabel;
+        private CharSequence mDisplayLabel;
         private Drawable mDisplayIcon;
         private Drawable mBadge;
-        private final CharSequence mExtendedInfo;
+        private CharSequence mExtendedInfo;
         private final Intent mResolvedIntent;
         private final List<Intent> mSourceIntents = new ArrayList<>();
         private boolean mIsSuspended;
 
+        public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, Intent pOrigIntent) {
+            this(originalIntent, pri, null /*mDisplayLabel*/, null /*mExtendedInfo*/, pOrigIntent);
+        }
+
         public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
                 CharSequence pInfo, Intent pOrigIntent) {
             mSourceIntents.add(originalIntent);
@@ -1448,9 +1452,26 @@
         }
 
         public CharSequence getDisplayLabel() {
+            if (mDisplayLabel == null) {
+                ResolveInfoPresentationGetter pg = makePresentationGetter(mResolveInfo);
+                mDisplayLabel = pg.getLabel();
+                mExtendedInfo = pg.getSubLabel();
+            }
             return mDisplayLabel;
         }
 
+        public boolean hasDisplayLabel() {
+            return mDisplayLabel != null;
+        }
+
+        public void setDisplayLabel(CharSequence displayLabel) {
+            mDisplayLabel = displayLabel;
+        }
+
+        public void setExtendedInfo(CharSequence extendedInfo) {
+            mExtendedInfo = extendedInfo;
+        }
+
         public Drawable getDisplayIcon() {
             return mDisplayIcon;
         }
@@ -1624,7 +1645,7 @@
         private final List<ResolveInfo> mBaseResolveList;
         protected ResolveInfo mLastChosen;
         private DisplayResolveInfo mOtherProfile;
-        private ResolverListController mResolverListController;
+        ResolverListController mResolverListController;
         private int mPlaceholderCount;
         private boolean mAllTargetsAreBrowsers = false;
 
@@ -1785,27 +1806,7 @@
                         --placeholderCount;
                     }
                     setPlaceholderCount(placeholderCount);
-                    AsyncTask<List<ResolvedComponentInfo>,
-                            Void,
-                            List<ResolvedComponentInfo>> sortingTask =
-                            new AsyncTask<List<ResolvedComponentInfo>,
-                                    Void,
-                                    List<ResolvedComponentInfo>>() {
-                        @Override
-                        protected List<ResolvedComponentInfo> doInBackground(
-                                List<ResolvedComponentInfo>... params) {
-                            mResolverListController.sort(params[0]);
-                            return params[0];
-                        }
-
-                        @Override
-                        protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
-                            processSortedList(sortedComponents);
-                            bindProfileView();
-                            notifyDataSetChanged();
-                        }
-                    };
-                    sortingTask.execute(currentResolveList);
+                    createSortingTask().execute(currentResolveList);
                     postListReadyRunnable();
                     return false;
                 } else {
@@ -1818,8 +1819,29 @@
             }
         }
 
+        AsyncTask<List<ResolvedComponentInfo>,
+                Void,
+                List<ResolvedComponentInfo>> createSortingTask() {
+            return new AsyncTask<List<ResolvedComponentInfo>,
+                    Void,
+                    List<ResolvedComponentInfo>>() {
+                @Override
+                protected List<ResolvedComponentInfo> doInBackground(
+                        List<ResolvedComponentInfo>... params) {
+                    mResolverListController.sort(params[0]);
+                    return params[0];
+                }
 
-        private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
+                @Override
+                protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
+                    processSortedList(sortedComponents);
+                    bindProfileView();
+                    notifyDataSetChanged();
+                }
+            };
+        }
+
+        void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
             int N;
             if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
                 mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
@@ -1865,9 +1887,7 @@
                     final ResolveInfo ri = rci.getResolveInfoAt(0);
                     if (ri != null) {
                         mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
-
-                        ResolveInfoPresentationGetter pg = makePresentationGetter(ri);
-                        addResolveInfoWithAlternates(rci, pg.getSubLabel(), pg.getLabel());
+                        addResolveInfoWithAlternates(rci);
                     }
                 }
             }
@@ -1914,14 +1934,12 @@
             return mFilterLastUsed;
         }
 
-        private void addResolveInfoWithAlternates(ResolvedComponentInfo rci,
-                CharSequence extraInfo, CharSequence roLabel) {
+        private void addResolveInfoWithAlternates(ResolvedComponentInfo rci) {
             final int count = rci.getCount();
             final Intent intent = rci.getIntentAt(0);
             final ResolveInfo add = rci.getResolveInfoAt(0);
             final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent);
-            final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel,
-                    extraInfo, replaceIntent);
+            final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, replaceIntent);
             addResolveInfo(dri);
             if (replaceIntent == intent) {
                 // Only add alternates if we didn't get a specific replacement from
@@ -2053,20 +2071,11 @@
                 return;
             }
 
-            final CharSequence label = info.getDisplayLabel();
-            if (!TextUtils.equals(holder.text.getText(), label)) {
-                holder.text.setText(info.getDisplayLabel());
-            }
-
-            // Always show a subLabel for visual consistency across list items. Show an empty
-            // subLabel if the subLabel is the same as the label
-            CharSequence subLabel = info.getExtendedInfo();
-            if (TextUtils.equals(label, subLabel)) subLabel = null;
-
-            if (!TextUtils.equals(holder.text2.getText(), subLabel)
-                    && !TextUtils.isEmpty(subLabel)) {
-                holder.text2.setVisibility(View.VISIBLE);
-                holder.text2.setText(subLabel);
+            if (info instanceof DisplayResolveInfo
+                    && !((DisplayResolveInfo) info).hasDisplayLabel()) {
+                getLoadLabelTask((DisplayResolveInfo) info, holder).execute();
+            } else {
+                holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo());
             }
 
             if (info.isSuspended()) {
@@ -2084,6 +2093,9 @@
         }
     }
 
+    protected LoadLabelTask getLoadLabelTask(DisplayResolveInfo info, ViewHolder holder) {
+        return new LoadLabelTask(info, holder);
+    }
 
     @VisibleForTesting
     public static final class ResolvedComponentInfo {
@@ -2147,6 +2159,24 @@
             text2 = (TextView) view.findViewById(com.android.internal.R.id.text2);
             icon = (ImageView) view.findViewById(R.id.icon);
         }
+
+        public void bindLabel(CharSequence label, CharSequence subLabel) {
+            if (!TextUtils.equals(text.getText(), label)) {
+                text.setText(label);
+            }
+
+            // Always show a subLabel for visual consistency across list items. Show an empty
+            // subLabel if the subLabel is the same as the label
+            if (TextUtils.equals(label, subLabel)) {
+                subLabel = null;
+            }
+
+            if (!TextUtils.equals(text2.getText(), subLabel)
+                    && !TextUtils.isEmpty(subLabel)) {
+                text2.setVisibility(View.VISIBLE);
+                text2.setText(subLabel);
+            }
+        }
     }
 
     class ItemClickListener implements AdapterView.OnItemClickListener,
@@ -2199,6 +2229,34 @@
 
     }
 
+    protected class LoadLabelTask extends AsyncTask<Void, Void, CharSequence[]> {
+        private final DisplayResolveInfo mDisplayResolveInfo;
+        private final ViewHolder mHolder;
+
+        protected LoadLabelTask(DisplayResolveInfo dri, ViewHolder holder) {
+            mDisplayResolveInfo = dri;
+            mHolder = holder;
+        }
+
+
+        @Override
+        protected CharSequence[] doInBackground(Void... voids) {
+            ResolveInfoPresentationGetter pg =
+                    makePresentationGetter(mDisplayResolveInfo.mResolveInfo);
+            return new CharSequence[] {
+                    pg.getLabel(),
+                    pg.getSubLabel()
+            };
+        }
+
+        @Override
+        protected void onPostExecute(CharSequence[] result) {
+            mDisplayResolveInfo.setDisplayLabel(result[0]);
+            mDisplayResolveInfo.setExtendedInfo(result[1]);
+            mHolder.bindLabel(result[0], result[1]);
+        }
+    }
+
     class LoadIconTask extends AsyncTask<Void, Void, Drawable> {
         protected final DisplayResolveInfo mDisplayResolveInfo;
         private final ResolveInfo mResolveInfo;
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index a390611..28a8a86 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -35,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.PriorityQueue;
 import java.util.concurrent.CountDownLatch;
 
 /**
@@ -230,22 +231,27 @@
         }
     }
 
-    @VisibleForTesting
-    @WorkerThread
-    public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
+    private void compute(List<ResolverActivity.ResolvedComponentInfo> inputList)
+            throws InterruptedException {
         if (mResolverComparator == null) {
             Log.d(TAG, "Comparator has already been destroyed; skipped.");
             return;
         }
+        final CountDownLatch finishComputeSignal = new CountDownLatch(1);
+        ComputeCallback callback = new ComputeCallback(finishComputeSignal);
+        mResolverComparator.setCallBack(callback);
+        mResolverComparator.compute(inputList);
+        finishComputeSignal.await();
+        isComputed = true;
+    }
+
+    @VisibleForTesting
+    @WorkerThread
+    public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
         try {
             long beforeRank = System.currentTimeMillis();
             if (!isComputed) {
-                final CountDownLatch finishComputeSignal = new CountDownLatch(1);
-                ComputeCallback callback = new ComputeCallback(finishComputeSignal);
-                mResolverComparator.setCallBack(callback);
-                mResolverComparator.compute(inputList);
-                finishComputeSignal.await();
-                isComputed = true;
+                compute(inputList);
             }
             Collections.sort(inputList, mResolverComparator);
 
@@ -258,6 +264,61 @@
         }
     }
 
+    @VisibleForTesting
+    @WorkerThread
+    public void topK(List<ResolverActivity.ResolvedComponentInfo> inputList, int k) {
+        if (inputList == null || inputList.isEmpty() || k <= 0) {
+            return;
+        }
+        if (inputList.size() <= k) {
+            // Fall into normal sort when number of ranked elements
+            // needed is not smaller than size of input list.
+            sort(inputList);
+            return;
+        }
+        try {
+            long beforeRank = System.currentTimeMillis();
+            if (!isComputed) {
+                compute(inputList);
+            }
+
+            // Top of this heap has lowest rank.
+            PriorityQueue<ResolverActivity.ResolvedComponentInfo> minHeap = new PriorityQueue<>(k,
+                    (o1, o2) -> -mResolverComparator.compare(o1, o2));
+            final int size = inputList.size();
+            // Use this pointer to keep track of the position of next element
+            // to update in input list, starting from the last position.
+            int pointer = size - 1;
+            minHeap.addAll(inputList.subList(size - k, size));
+            for (int i = size - k - 1; i >= 0; --i) {
+                ResolverActivity.ResolvedComponentInfo ci = inputList.get(i);
+                if (-mResolverComparator.compare(ci, minHeap.peek()) > 0) {
+                    // When ranked higher than top of heap, remove top of heap,
+                    // update input list with it, add this new element to heap.
+                    inputList.set(pointer--, minHeap.poll());
+                    minHeap.add(ci);
+                } else {
+                    // When ranked no higher than top of heap, update input list
+                    // with this new element.
+                    inputList.set(pointer--, ci);
+                }
+            }
+
+            // Now we have top k elements in heap, update first
+            // k positions of input list with them.
+            while (!minHeap.isEmpty()) {
+                inputList.set(pointer--, minHeap.poll());
+            }
+
+            long afterRank = System.currentTimeMillis();
+            if (DEBUG) {
+                Log.d(TAG, "Time Cost for top " + k + " targets: "
+                        + Long.toString(afterRank - beforeRank));
+            }
+        } catch (InterruptedException e) {
+            Log.e(TAG, "Compute & greatestOf was interrupted: " + e);
+        }
+    }
 
     private static boolean isSameResolvedComponent(ResolveInfo a,
             ResolverActivity.ResolvedComponentInfo b) {
diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java
index 72b0ad7..e0eb9af 100644
--- a/core/java/com/android/internal/compat/ChangeReporter.java
+++ b/core/java/com/android/internal/compat/ChangeReporter.java
@@ -21,6 +21,7 @@
 import android.util.StatsLog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -37,7 +38,7 @@
     private static final String TAG = "CompatibilityChangeReporter";
     private int mSource;
 
-    private final class ChangeReport {
+    private static final class ChangeReport {
         long mChangeId;
         int mState;
 
@@ -65,9 +66,13 @@
     @GuardedBy("mReportedChanges")
     private final Map<Integer, Set<ChangeReport>> mReportedChanges;
 
+    // When true will of every time to debug (logcat).
+    private boolean mDebugLogAll;
+
     public ChangeReporter(int source) {
         mSource = source;
         mReportedChanges =  new HashMap<>();
+        mDebugLogAll = false;
     }
 
     /**
@@ -79,20 +84,76 @@
      * @param state    of the reported change - enabled/disabled/only logged
      */
     public void reportChange(int uid, long changeId, int state) {
-        ChangeReport report = new ChangeReport(changeId, state);
+        if (shouldWriteToStatsLog(uid, changeId, state)) {
+            StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
+                    state, mSource);
+        }
+        if (shouldWriteToDebug(uid, changeId, state)) {
+            debugLog(uid, changeId, state);
+        }
+        markAsReported(uid, new ChangeReport(changeId, state));
+    }
+
+    /**
+     * Start logging all the time to logcat.
+     */
+    public void startDebugLogAll() {
+        mDebugLogAll = true;
+    }
+
+    /**
+     * Stop logging all the time to logcat.
+     */
+    public void stopDebugLogAll() {
+        mDebugLogAll = false;
+    }
+
+
+    /**
+     * Returns whether the next report should be logged to statsLog.
+     *
+     * @param uid      affected by the change
+     * @param changeId the reported change id
+     * @param state    of the reported change - enabled/disabled/only logged
+     * @return true if the report should be logged
+     */
+    @VisibleForTesting
+    public boolean shouldWriteToStatsLog(int uid, long changeId, int state) {
+        return !isAlreadyReported(uid, new ChangeReport(changeId, state));
+    }
+
+    /**
+     * Returns whether the next report should be logged to logcat.
+     *
+     * @param uid      affected by the change
+     * @param changeId the reported change id
+     * @param state    of the reported change - enabled/disabled/only logged
+     * @return true if the report should be logged
+     */
+    @VisibleForTesting
+    public boolean shouldWriteToDebug(int uid, long changeId, int state) {
+        return mDebugLogAll || !isAlreadyReported(uid, new ChangeReport(changeId, state));
+    }
+
+    private boolean isAlreadyReported(int uid, ChangeReport report) {
+        synchronized (mReportedChanges) {
+            Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
+            if (reportedChangesForUid == null) {
+                return false;
+            } else {
+                return reportedChangesForUid.contains(report);
+            }
+        }
+    }
+
+    private void markAsReported(int uid, ChangeReport report) {
         synchronized (mReportedChanges) {
             Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
             if (reportedChangesForUid == null) {
                 mReportedChanges.put(uid, new HashSet<ChangeReport>());
                 reportedChangesForUid = mReportedChanges.get(uid);
             }
-            if (!reportedChangesForUid.contains(report)) {
-                debugLog(uid, changeId, state);
-                StatsLog.write(StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid, changeId,
-                        state, mSource);
-                reportedChangesForUid.add(report);
-            }
-
+            reportedChangesForUid.add(report);
         }
     }
 
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 4099cfa..8391ad2 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -49,9 +49,10 @@
      * 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 userId      The ID of the user that the operation is done for.
      * @param packageName The package name of the app in question.
      */
-     void reportChangeByPackageName(long changeId, in String packageName);
+     void reportChangeByPackageName(long changeId, in String packageName, int userId);
 
     /**
      * Reports that a compatibility change is affecting an app process now.
@@ -86,7 +87,7 @@
      * be called when implementing functionality on behalf of the affected app.
      *
      * <p>Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a package name
-     * instead of an {@link ApplicationInfo}
+     * and userId 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.
      *
@@ -100,9 +101,10 @@
      *
      * @param changeId    The ID of the compatibility change in question.
      * @param packageName The package name of the app in question.
+     * @param userId      The ID of the user that the operation is done for.
      * @return {@code true} if the change is enabled for the current app.
      */
-    boolean isChangeEnabledByPackageName(long changeId, in String packageName);
+    boolean isChangeEnabledByPackageName(long changeId, in String packageName, int userId);
 
     /**
      * Query if a given compatibility change is enabled for an app process. This method should
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 158700b..363e549 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -184,6 +184,12 @@
         System.loadLibrary("android");
         System.loadLibrary("compiler_rt");
         System.loadLibrary("jnigraphics");
+
+        try {
+            System.loadLibrary("sfplugin_ccodec");
+        } catch (Error | RuntimeException e) {
+            // tolerate missing sfplugin_ccodec which is only present on Codec 2 devices
+        }
     }
 
     native private static void nativePreloadAppProcessHALs();
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c8ba52a..317469e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -23,6 +23,7 @@
 import android.service.notification.StatusBarNotification;
 
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.view.AppearanceRegion;
 
 /** @hide */
 oneway interface IStatusBar
@@ -56,7 +57,7 @@
             int mask, in Rect fullscreenBounds, in Rect dockedBounds,
             boolean navbarColorManagedByIme);
 
-    void topAppWindowChanged(int displayId, boolean menuVisible);
+    void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
     void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
             boolean showImeSwitcher, boolean isMultiClientImeEnabled);
     void setWindowState(int display, int window, int state);
@@ -154,12 +155,12 @@
     // Used to show the authentication dialog (Biometrics, Device Credential)
     void showAuthenticationDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver,
             int biometricModality, boolean requireConfirmation, int userId, String opPackageName);
-    // Used to notify the authentication dialog that a biometric has been authenticated or rejected
-    void onBiometricAuthenticated(boolean authenticated, String failureReason);
+    // Used to notify the authentication dialog that a biometric has been authenticated
+    void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
     void onBiometricHelp(String message);
-    // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onBiometricError(int errorCode, String error);
+    // Used to show an error - the dialog will dismiss after a certain amount of time
+    void onBiometricError(int modality, int error, int vendorCode);
     // Used to hide the authentication dialog, e.g. when the application cancels authentication
     void hideAuthenticationDialog();
 
@@ -172,4 +173,38 @@
      * Notifies System UI whether the recents animation is running or not.
      */
     void onRecentsAnimationStateChanged(boolean running);
+
+    /**
+     * Notifies System UI side of system bar appearance change on the specified display.
+     *
+     * @param displayId the ID of the display to notify
+     * @param appearance the appearance of the focused window. The light top bar appearance is not
+     *                   controlled here, but primaryAppearance and secondaryAppearance.
+     * @param appearanceRegions a set of appearances which will be only applied in their own bounds.
+     *                         This is for system bars which across multiple stack, e.g., status
+     *                         bar, that the bar can have partial appearances in corresponding
+     *                         stacks.
+     * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
+     */
+    void onSystemBarAppearanceChanged(int displayId, int appearance,
+            in AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme);
+
+    /**
+     * Notifies System UI to show transient bars. The transient bars are system bars, e.g., status
+     * bar and navigation bar which are temporarily visible to the user.
+     *
+     * @param displayId the ID of the display to notify.
+     * @param types the internal insets types of the bars are about to show transiently.
+     */
+    void showTransient(int displayId, in int[] types);
+
+    /**
+     * Notifies System UI to abort the transient state of system bars, which prevents the bars being
+     * hidden automatically. This is usually called when the app wants to show the permanent system
+     * bars again.
+     *
+     * @param displayId the ID of the display to notify.
+     * @param types the internal insets types of the bars are about to abort the transient state.
+     */
+    void abortTransient(int displayId, in int[] types);
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 659134a..499a4d2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -104,12 +104,12 @@
     // Used to show the authentication dialog (Biometrics, Device Credential)
     void showAuthenticationDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver,
             int biometricModality, boolean requireConfirmation, int userId, String opPackageName);
-    // Used to notify the authentication dialog that a biometric has been authenticated or rejected
-    void onBiometricAuthenticated(boolean authenticated, String failureReason);
+    // Used to notify the authentication dialog that a biometric has been authenticated
+    void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
     void onBiometricHelp(String message);
-    // Used to set a message - the dialog will dismiss after a certain amount of time
-    void onBiometricError(int errorCode, String error);
+    // Used to show an error - the dialog will dismiss after a certain amount of time
+    void onBiometricError(int modality, int error, int vendorCode);
     // Used to hide the authentication dialog, e.g. when the application cancels authentication
     void hideAuthenticationDialog();
 }
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 6b0f8b2..4c3f04b 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -29,7 +29,6 @@
     public final ArrayMap<String, StatusBarIcon> mIcons;
     public final int mDisabledFlags1;                  // switch[0]
     public final int mSystemUiVisibility;              // switch[1]
-    public final boolean mMenuVisible;                 // switch[2]
     public final int mImeWindowVis;                    // switch[3]
     public final int mImeBackDisposition;              // switch[4]
     public final boolean mShowImeSwitcher;             // switch[5]
@@ -40,16 +39,18 @@
     public final Rect mFullscreenStackBounds;
     public final Rect mDockedStackBounds;
     public final boolean mNavbarColorManagedByIme;
+    public final boolean mAppFullscreen;
+    public final boolean mAppImmersive;
 
     public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
-            int systemUiVisibility, boolean menuVisible, int imeWindowVis, int imeBackDisposition,
+            int systemUiVisibility, int imeWindowVis, int imeBackDisposition,
             boolean showImeSwitcher, int disabledFlags2, int fullscreenStackSysUiVisibility,
             int dockedStackSysUiVisibility, IBinder imeToken, Rect fullscreenStackBounds,
-            Rect dockedStackBounds, boolean navbarColorManagedByIme) {
+            Rect dockedStackBounds, boolean navbarColorManagedByIme, boolean appFullscreen,
+            boolean appImmersive) {
         mIcons = new ArrayMap<>(icons);
         mDisabledFlags1 = disabledFlags1;
         mSystemUiVisibility = systemUiVisibility;
-        mMenuVisible = menuVisible;
         mImeWindowVis = imeWindowVis;
         mImeBackDisposition = imeBackDisposition;
         mShowImeSwitcher = showImeSwitcher;
@@ -60,6 +61,8 @@
         mFullscreenStackBounds = fullscreenStackBounds;
         mDockedStackBounds = dockedStackBounds;
         mNavbarColorManagedByIme = navbarColorManagedByIme;
+        mAppFullscreen = appFullscreen;
+        mAppImmersive = appImmersive;
     }
 
     @Override
@@ -72,7 +75,6 @@
         dest.writeTypedArrayMap(mIcons, flags);
         dest.writeInt(mDisabledFlags1);
         dest.writeInt(mSystemUiVisibility);
-        dest.writeBoolean(mMenuVisible);
         dest.writeInt(mImeWindowVis);
         dest.writeInt(mImeBackDisposition);
         dest.writeBoolean(mShowImeSwitcher);
@@ -83,6 +85,8 @@
         dest.writeTypedObject(mFullscreenStackBounds, flags);
         dest.writeTypedObject(mDockedStackBounds, flags);
         dest.writeBoolean(mNavbarColorManagedByIme);
+        dest.writeBoolean(mAppFullscreen);
+        dest.writeBoolean(mAppImmersive);
     }
 
     /**
@@ -96,7 +100,6 @@
                             source.createTypedArrayMap(StatusBarIcon.CREATOR);
                     final int disabledFlags1 = source.readInt();
                     final int systemUiVisibility = source.readInt();
-                    final boolean menuVisible = source.readBoolean();
                     final int imeWindowVis = source.readInt();
                     final int imeBackDisposition = source.readInt();
                     final boolean showImeSwitcher = source.readBoolean();
@@ -107,11 +110,13 @@
                     final Rect fullscreenStackBounds = source.readTypedObject(Rect.CREATOR);
                     final Rect dockedStackBounds = source.readTypedObject(Rect.CREATOR);
                     final boolean navbarColorManagedByIme = source.readBoolean();
+                    final boolean appFullscreen = source.readBoolean();
+                    final boolean appImmersive = source.readBoolean();
                     return new RegisterStatusBarResult(icons, disabledFlags1, systemUiVisibility,
-                            menuVisible, imeWindowVis, imeBackDisposition, showImeSwitcher,
-                            disabledFlags2, fullscreenStackSysUiVisibility,
-                            dockedStackSysUiVisibility, imeToken, fullscreenStackBounds,
-                            dockedStackBounds, navbarColorManagedByIme);
+                            imeWindowVis, imeBackDisposition, showImeSwitcher, disabledFlags2,
+                            fullscreenStackSysUiVisibility, dockedStackSysUiVisibility, imeToken,
+                            fullscreenStackBounds, dockedStackBounds, navbarColorManagedByIme,
+                            appFullscreen, appImmersive);
                 }
 
                 @Override
diff --git a/telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl b/core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl
similarity index 100%
rename from telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl
rename to core/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
similarity index 99%
rename from telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
rename to core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 90019ee..084a3cc 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -29,6 +29,9 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
+/**
+ * {@hide}
+ */
 oneway interface IPhoneStateListener {
     void onServiceStateChanged(in ServiceState serviceState);
     void onSignalStrengthChanged(int asu);
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
similarity index 100%
rename from telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
rename to core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/core/java/com/android/internal/view/AppearanceRegion.aidl
similarity index 82%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to core/java/com/android/internal/view/AppearanceRegion.aidl
index d2ec357..1638bf5 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/core/java/com/android/internal/view/AppearanceRegion.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package com.android.internal.view;
 
-parcelable TimeSignal;
\ No newline at end of file
+parcelable AppearanceRegion;
diff --git a/core/java/com/android/internal/view/AppearanceRegion.java b/core/java/com/android/internal/view/AppearanceRegion.java
new file mode 100644
index 0000000..1a0cb4b
--- /dev/null
+++ b/core/java/com/android/internal/view/AppearanceRegion.java
@@ -0,0 +1,142 @@
+/*
+ * 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.internal.view;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+import android.os.Parcelable;
+import android.view.InsetsFlags;
+import android.view.ViewDebug;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Specifies which region applies which appearance.
+ */
+@DataClass
+public class AppearanceRegion implements Parcelable {
+
+    private int mAppearance;
+    private @NonNull Rect mBounds;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        final AppearanceRegion sa = (AppearanceRegion) o;
+        return mAppearance == sa.mAppearance && mBounds.equals(sa.mBounds);
+    }
+
+    @Override
+    public String toString() {
+        final String appearanceString =
+                ViewDebug.flagsToString(InsetsFlags.class, "appearance", mAppearance);
+        return "AppearanceRegion{" + appearanceString + " bounds=" + mBounds.toShortString() + "}";
+    }
+
+
+
+    // Code below generated by codegen v1.0.7.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/view/AppearanceRegion.java
+
+
+    @DataClass.Generated.Member
+    public AppearanceRegion(
+            int appearance,
+            @NonNull Rect bounds) {
+        this.mAppearance = appearance;
+        this.mBounds = bounds;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBounds);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public int getAppearance() {
+        return mAppearance;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Rect getBounds() {
+        return mBounds;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeInt(mAppearance);
+        dest.writeTypedObject(mBounds, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected AppearanceRegion(android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        int appearance = in.readInt();
+        Rect bounds = (Rect) in.readTypedObject(Rect.CREATOR);
+
+        this.mAppearance = appearance;
+        this.mBounds = bounds;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mBounds);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AppearanceRegion> CREATOR
+            = new Parcelable.Creator<AppearanceRegion>() {
+        @Override
+        public AppearanceRegion[] newArray(int size) {
+            return new AppearanceRegion[size];
+        }
+
+        @Override
+        public AppearanceRegion createFromParcel(android.os.Parcel in) {
+            return new AppearanceRegion(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1570909617357L,
+            codegenVersion = "1.0.7",
+            sourceFile = "frameworks/base/core/java/com/android/internal/view/AppearanceRegion.java",
+            inputSignatures = "private  int mAppearance\nprivate @android.annotation.NonNull android.graphics.Rect mBounds\npublic @java.lang.Override boolean equals(java.lang.Object)\npublic @java.lang.Override java.lang.String toString()\nclass AppearanceRegion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+    @Deprecated
+    private void __metadata() {}
+
+}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index b626fc6..897b982 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -24,6 +24,7 @@
 import android.security.keystore.recovery.KeyChainProtectionParams;
 import android.security.keystore.recovery.RecoveryCertPath;
 import com.android.internal.widget.ICheckCredentialProgressCallback;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
 
 import java.util.Map;
@@ -42,19 +43,16 @@
     long getLong(in String key, in long defaultValue, in int userId);
     @UnsupportedAppUsage
     String getString(in String key, in String defaultValue, in int userId);
-    boolean setLockCredential(in byte[] credential, int type, in byte[] savedCredential, int requestedQuality, int userId, boolean allowUntrustedChange);
+    boolean setLockCredential(in LockscreenCredential credential, in LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange);
     void resetKeyStore(int userId);
-    VerifyCredentialResponse checkCredential(in byte[] credential, int type, int userId,
+    VerifyCredentialResponse checkCredential(in LockscreenCredential credential, int userId,
             in ICheckCredentialProgressCallback progressCallback);
-    VerifyCredentialResponse verifyCredential(in byte[] credential, int type, long challenge, int userId);
-    VerifyCredentialResponse verifyTiedProfileChallenge(in byte[] credential, int type, long challenge, int userId);
+    VerifyCredentialResponse verifyCredential(in LockscreenCredential credential, long challenge, int userId);
+    VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, long challenge, int userId);
     boolean checkVoldPassword(int userId);
-    @UnsupportedAppUsage
-    boolean havePattern(int userId);
-    @UnsupportedAppUsage
-    boolean havePassword(int userId);
-    byte[] getHashFactor(in byte[] currentCredential, int userId);
-    void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in byte[] managedUserPassword);
+    int getCredentialType(int userId);
+    byte[] getHashFactor(in LockscreenCredential currentCredential, int userId);
+    void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in LockscreenCredential managedUserPassword);
     boolean getSeparateProfileChallengeEnabled(int userId);
     void registerStrongAuthTracker(in IStrongAuthTracker tracker);
     void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 8fea703..b534213 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -17,9 +17,6 @@
 package com.android.internal.widget;
 
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
@@ -59,10 +56,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 
-import libcore.util.HexEncoding;
-
 import com.google.android.collect.Lists;
 
+import libcore.util.HexEncoding;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.security.MessageDigest;
@@ -117,13 +114,19 @@
     // NOTE: When modifying this, make sure credential sufficiency validation logic is intact.
     public static final int CREDENTIAL_TYPE_NONE = -1;
     public static final int CREDENTIAL_TYPE_PATTERN = 1;
-    public static final int CREDENTIAL_TYPE_PASSWORD = 2;
+    // This is the legacy value persisted on disk. Never return it to clients, but internally
+    // we still need it to handle upgrade cases.
+    public static final int CREDENTIAL_TYPE_PASSWORD_OR_PIN = 2;
+    public static final int CREDENTIAL_TYPE_PIN = 3;
+    public static final int CREDENTIAL_TYPE_PASSWORD = 4;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"CREDENTIAL_TYPE_"}, value = {
             CREDENTIAL_TYPE_NONE,
             CREDENTIAL_TYPE_PATTERN,
-            CREDENTIAL_TYPE_PASSWORD, // Either pin or password.
+            CREDENTIAL_TYPE_PASSWORD,
+            CREDENTIAL_TYPE_PIN,
+            // CREDENTIAL_TYPE_PASSWORD_OR_PIN is missing on purpose.
     })
     public @interface CredentialType {}
 
@@ -169,6 +172,7 @@
 
     public static final String SYNTHETIC_PASSWORD_HANDLE_KEY = "sp-handle";
     public static final String SYNTHETIC_PASSWORD_ENABLED_KEY = "enable-sp";
+    public static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1;
     private static final String HISTORY_DELIMITER = ",";
 
     @UnsupportedAppUsage
@@ -372,8 +376,8 @@
      *
      * @param credential The credential to check.
      * @param challenge The challenge to verify against the credential
-     * @return the attestation that the challenge was verified, or null
      * @param userId The user whose credential is being verified
+     * @return the attestation that the challenge was verified, or null
      * @throws RequestThrottledException if credential verification is being throttled due to
      *         to many incorrect attempts.
      * @throws IllegalStateException if called on the main thread.
@@ -383,7 +387,7 @@
         throwIfCalledOnMainThread();
         try {
             VerifyCredentialResponse response = getLockSettings().verifyCredential(
-                    credential.getCredential(), credential.getType(), challenge, userId);
+                    credential, challenge, userId);
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
                 return response.getPayload();
             } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
@@ -392,6 +396,7 @@
                 return null;
             }
         } catch (RemoteException re) {
+            Log.e(TAG, "failed to verify credential", re);
             return null;
         }
     }
@@ -413,8 +418,7 @@
         throwIfCalledOnMainThread();
         try {
             VerifyCredentialResponse response = getLockSettings().checkCredential(
-                    credential.getCredential(), credential.getType(),
-                    userId, wrapCallback(progressCallback));
+                    credential, userId, wrapCallback(progressCallback));
 
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
                 return true;
@@ -424,6 +428,7 @@
                 return false;
             }
         } catch (RemoteException re) {
+            Log.e(TAG, "failed to check credential", re);
             return false;
         }
     }
@@ -447,8 +452,7 @@
         throwIfCalledOnMainThread();
         try {
             VerifyCredentialResponse response =
-                    getLockSettings().verifyTiedProfileChallenge(
-                            credential.getCredential(), credential.getType(), challenge, userId);
+                    getLockSettings().verifyTiedProfileChallenge(credential, challenge, userId);
 
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
                 return response.getPayload();
@@ -458,6 +462,7 @@
                 return null;
             }
         } catch (RemoteException re) {
+            Log.e(TAG, "failed to verify tied profile credential", re);
             return null;
         }
     }
@@ -471,6 +476,7 @@
         try {
             return getLockSettings().checkVoldPassword(userId);
         } catch (RemoteException re) {
+            Log.e(TAG, "failed to check vold password", re);
             return false;
         }
     }
@@ -482,7 +488,7 @@
     public byte[] getPasswordHistoryHashFactor(@NonNull LockscreenCredential currentPassword,
             int userId) {
         try {
-            return getLockSettings().getHashFactor(currentPassword.getCredential(), userId);
+            return getLockSettings().getHashFactor(currentPassword, userId);
         } catch (RemoteException e) {
             Log.e(TAG, "failed to get hash factor", e);
             return null;
@@ -524,30 +530,6 @@
     }
 
     /**
-     * Check to see if the user has stored a lock pattern.
-     * @return Whether a saved pattern exists.
-     */
-    private boolean savedPatternExists(int userId) {
-        try {
-            return getLockSettings().havePattern(userId);
-        } catch (RemoteException re) {
-            return false;
-        }
-    }
-
-    /**
-     * Check to see if the user has stored a lock pattern.
-     * @return Whether a saved pattern exists.
-     */
-    private boolean savedPasswordExists(int userId) {
-        try {
-            return getLockSettings().havePassword(userId);
-        } catch (RemoteException re) {
-            return false;
-        }
-    }
-
-    /**
      * Return true if the user has ever chosen a pattern.  This is true even if the pattern is
      * currently cleared.
      *
@@ -568,22 +550,11 @@
     /**
      * Used by device policy manager to validate the current password
      * information it has.
+     * @Deprecated use {@link #getKeyguardStoredPasswordQuality}
      */
     @UnsupportedAppUsage
     public int getActivePasswordQuality(int userId) {
-        int quality = getKeyguardStoredPasswordQuality(userId);
-
-        if (isLockPasswordEnabled(quality, userId)) {
-            // Quality is a password and a password exists. Return the quality.
-            return quality;
-        }
-
-        if (isLockPatternEnabled(quality, userId)) {
-            // Quality is a pattern and a pattern exists. Return the quality.
-            return quality;
-        }
-
-        return PASSWORD_QUALITY_UNSPECIFIED;
+        return getKeyguardStoredPasswordQuality(userId);
     }
 
     /**
@@ -641,6 +612,22 @@
         return quality == PASSWORD_QUALITY_NUMERIC || quality == PASSWORD_QUALITY_NUMERIC_COMPLEX;
     }
 
+    /** Returns the canonical password quality corresponding to the given credential type. */
+    public static int credentialTypeToPasswordQuality(int credentialType) {
+        switch (credentialType) {
+            case CREDENTIAL_TYPE_NONE:
+                return PASSWORD_QUALITY_UNSPECIFIED;
+            case CREDENTIAL_TYPE_PATTERN:
+                return PASSWORD_QUALITY_SOMETHING;
+            case CREDENTIAL_TYPE_PIN:
+                return PASSWORD_QUALITY_NUMERIC;
+            case CREDENTIAL_TYPE_PASSWORD:
+                return PASSWORD_QUALITY_ALPHABETIC;
+            default:
+                throw new IllegalStateException("Unknown type: " + credentialType);
+        }
+    }
+
     /**
      * Save a new lockscreen credential.
      *
@@ -684,19 +671,12 @@
         }
         newCredential.checkLength();
 
-        final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
-        setKeyguardStoredPasswordQuality(newCredential.getQuality(), userHandle);
-
         try {
             if (!getLockSettings().setLockCredential(
-                    newCredential.getCredential(), newCredential.getType(),
-                    savedCredential.getCredential(),
-                    newCredential.getQuality(), userHandle, allowUntrustedChange)) {
-                setKeyguardStoredPasswordQuality(currentQuality, userHandle);
+                    newCredential, savedCredential, userHandle, allowUntrustedChange)) {
                 return false;
             }
-        } catch (RemoteException | RuntimeException e) {
-            setKeyguardStoredPasswordQuality(currentQuality, userHandle);
+        } catch (RemoteException e) {
             throw new RuntimeException("Unable to save lock password", e);
         }
 
@@ -904,14 +884,12 @@
      * @see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)
      *
      * @return stored password quality
+     * @deprecated use {@link #getCredentialTypeForUser(int)} instead
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int getKeyguardStoredPasswordQuality(int userHandle) {
-        return (int) getLong(PASSWORD_TYPE_KEY, PASSWORD_QUALITY_UNSPECIFIED, userHandle);
-    }
-
-    private void setKeyguardStoredPasswordQuality(int quality, int userHandle) {
-        setLong(PASSWORD_TYPE_KEY, quality, userHandle);
+        return credentialTypeToPasswordQuality(getCredentialTypeForUser(userHandle));
     }
 
     /**
@@ -920,17 +898,17 @@
      *
      * @param userHandle Managed profile user id
      * @param enabled True if separate challenge is enabled
-     * @param managedUserPassword Managed profile previous password. Null when {@code enabled} is
+     * @param profilePassword Managed profile previous password. Null when {@code enabled} is
      *            true
      */
     public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
-            LockscreenCredential managedUserPassword) {
+            LockscreenCredential profilePassword) {
         if (!isManagedProfile(userHandle)) {
             return;
         }
         try {
             getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
-                    managedUserPassword.getCredential());
+                    profilePassword);
             reportEnabledTrustAgentsChanged(userHandle);
         } catch (RemoteException e) {
             Log.e(TAG, "Couldn't update work profile challenge enabled");
@@ -1098,28 +1076,33 @@
     }
 
     /**
+     * Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE},
+     * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and
+     * {@link #CREDENTIAL_TYPE_PASSWORD}
+     */
+    public @CredentialType int getCredentialTypeForUser(int userHandle) {
+        try {
+            return getLockSettings().getCredentialType(userHandle);
+        } catch (RemoteException re) {
+            Log.e(TAG, "failed to get credential type", re);
+            return CREDENTIAL_TYPE_NONE;
+        }
+    }
+
+    /**
      * @param userId the user for which to report the value
      * @return Whether the lock screen is secured.
      */
     @UnsupportedAppUsage
     public boolean isSecure(int userId) {
-        int mode = getKeyguardStoredPasswordQuality(userId);
-        return isLockPatternEnabled(mode, userId) || isLockPasswordEnabled(mode, userId);
+        int type = getCredentialTypeForUser(userId);
+        return type != CREDENTIAL_TYPE_NONE;
     }
 
     @UnsupportedAppUsage
     public boolean isLockPasswordEnabled(int userId) {
-        return isLockPasswordEnabled(getKeyguardStoredPasswordQuality(userId), userId);
-    }
-
-    private boolean isLockPasswordEnabled(int mode, int userId) {
-        final boolean passwordEnabled = mode == PASSWORD_QUALITY_ALPHABETIC
-                || mode == PASSWORD_QUALITY_NUMERIC
-                || mode == PASSWORD_QUALITY_NUMERIC_COMPLEX
-                || mode == PASSWORD_QUALITY_ALPHANUMERIC
-                || mode == PASSWORD_QUALITY_COMPLEX
-                || mode == PASSWORD_QUALITY_MANAGED;
-        return passwordEnabled && savedPasswordExists(userId);
+        int type = getCredentialTypeForUser(userId);
+        return type == CREDENTIAL_TYPE_PASSWORD || type == CREDENTIAL_TYPE_PIN;
     }
 
     /**
@@ -1127,7 +1110,8 @@
      */
     @UnsupportedAppUsage
     public boolean isLockPatternEnabled(int userId) {
-        return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
+        int type = getCredentialTypeForUser(userId);
+        return type == CREDENTIAL_TYPE_PATTERN;
     }
 
     @Deprecated
@@ -1143,10 +1127,6 @@
         setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId);
     }
 
-    private boolean isLockPatternEnabled(int mode, int userId) {
-        return mode == PASSWORD_QUALITY_SOMETHING && savedPatternExists(userId);
-    }
-
     /**
      * @return Whether the visible pattern is enabled.
      */
@@ -1543,8 +1523,8 @@
      * @param userHandle The user who's lock credential to be changed
      * @return {@code true} if the operation is successful.
      */
-    public boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle,
-            byte[] token, int userHandle) {
+    public boolean setLockCredentialWithToken(@NonNull LockscreenCredential credential,
+            long tokenHandle, byte[] token, int userHandle) {
         if (!hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires the lock screen feature.");
@@ -1552,19 +1532,8 @@
         credential.checkLength();
         LockSettingsInternal localService = getLockSettingsInternal();
 
-        final int currentQuality = getKeyguardStoredPasswordQuality(userHandle);
-        setKeyguardStoredPasswordQuality(credential.getQuality(), userHandle);
-
-        try {
-            if (!localService.setLockCredentialWithToken(credential.getCredential(),
-                    credential.getType(),
-                    tokenHandle, token, credential.getType(), userHandle)) {
-                setKeyguardStoredPasswordQuality(currentQuality, userHandle);
-                return false;
-            }
-        } catch (RuntimeException e) {
-            setKeyguardStoredPasswordQuality(currentQuality, userHandle);
-            throw new RuntimeException("Unable to save lock credential", e);
+        if (!localService.setLockCredentialWithToken(credential, tokenHandle, token, userHandle)) {
+            return false;
         }
 
         onPostPasswordChanged(credential, userHandle);
@@ -1765,7 +1734,8 @@
     }
 
     public boolean isSyntheticPasswordEnabled() {
-        return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM) != 0;
+        return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT,
+                UserHandle.USER_SYSTEM) != 0;
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/LockSettingsInternal.java b/core/java/com/android/internal/widget/LockSettingsInternal.java
index aab2f4b..dd05576 100644
--- a/core/java/com/android/internal/widget/LockSettingsInternal.java
+++ b/core/java/com/android/internal/widget/LockSettingsInternal.java
@@ -59,8 +59,8 @@
      *
      * @return true if password is set.
      */
-    public abstract boolean setLockCredentialWithToken(byte[] credential, int type,
-            long tokenHandle, byte[] token, int requestedQuality, int userId);
+    public abstract boolean setLockCredentialWithToken(LockscreenCredential credential,
+            long tokenHandle, byte[] token, int userId);
 
     public abstract boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId);
 
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/core/java/com/android/internal/widget/LockscreenCredential.aidl
similarity index 75%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to core/java/com/android/internal/widget/LockscreenCredential.aidl
index d2ec357..22501ff 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/core/java/com/android/internal/widget/LockscreenCredential.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package com.android.internal.widget;
 
-parcelable TimeSignal;
\ No newline at end of file
+/**
+ * A class representing a lockscreen credential.
+ */
+parcelable LockscreenCredential;
+
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index 19e6d97..f456349 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -16,14 +16,11 @@
 
 package com.android.internal.widget;
 
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -61,9 +58,6 @@
     // Stores raw credential bytes, or null if credential has been zeroized. An empty password
     // is represented as a byte array of length 0.
     private byte[] mCredential;
-    // Store the quality of the password, this is used to distinguish between pin
-    // (PASSWORD_QUALITY_NUMERIC) and password (PASSWORD_QUALITY_ALPHABETIC).
-    private final int mQuality;
 
     /**
      * Private constructor, use static builder methods instead.
@@ -72,15 +66,18 @@
      * LockscreenCredential will only store the reference internally without copying. This is to
      * minimize the number of extra copies introduced.
      */
-    private LockscreenCredential(int type, int quality, byte[] credential) {
+    private LockscreenCredential(int type, byte[] credential) {
         Preconditions.checkNotNull(credential);
         if (type == CREDENTIAL_TYPE_NONE) {
             Preconditions.checkArgument(credential.length == 0);
         } else {
+            // Do not allow constructing a CREDENTIAL_TYPE_PASSWORD_OR_PIN object.
+            Preconditions.checkArgument(type == CREDENTIAL_TYPE_PIN
+                    || type == CREDENTIAL_TYPE_PASSWORD
+                    || type == CREDENTIAL_TYPE_PATTERN);
             Preconditions.checkArgument(credential.length > 0);
         }
         mType = type;
-        mQuality = quality;
         mCredential = credential;
     }
 
@@ -88,8 +85,7 @@
      * Creates a LockscreenCredential object representing empty password.
      */
     public static LockscreenCredential createNone() {
-        return new LockscreenCredential(CREDENTIAL_TYPE_NONE, PASSWORD_QUALITY_UNSPECIFIED,
-                new byte[0]);
+        return new LockscreenCredential(CREDENTIAL_TYPE_NONE, new byte[0]);
     }
 
     /**
@@ -97,7 +93,6 @@
      */
     public static LockscreenCredential createPattern(@NonNull List<LockPatternView.Cell> pattern) {
         return new LockscreenCredential(CREDENTIAL_TYPE_PATTERN,
-                PASSWORD_QUALITY_SOMETHING,
                 LockPatternUtils.patternToByteArray(pattern));
     }
 
@@ -106,16 +101,25 @@
      */
     public static LockscreenCredential createPassword(@NonNull CharSequence password) {
         return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,
-                PASSWORD_QUALITY_ALPHABETIC,
                 charSequenceToByteArray(password));
     }
 
     /**
+     * Creates a LockscreenCredential object representing a managed password for profile with
+     * unified challenge. This credentiall will have type {@code CREDENTIAL_TYPE_PASSWORD} for now.
+     * TODO: consider add a new credential type for this. This can then supersede the
+     * isLockTiedToParent argument in various places in LSS.
+     */
+    public static LockscreenCredential createManagedPassword(@NonNull byte[] password) {
+        return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,
+                Arrays.copyOf(password, password.length));
+    }
+
+    /**
      * Creates a LockscreenCredential object representing the given numeric PIN.
      */
     public static LockscreenCredential createPin(@NonNull CharSequence pin) {
-        return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,
-                PASSWORD_QUALITY_NUMERIC,
+        return new LockscreenCredential(CREDENTIAL_TYPE_PIN,
                 charSequenceToByteArray(pin));
     }
 
@@ -143,27 +147,13 @@
         }
     }
 
-    /**
-     * Create a LockscreenCredential object based on raw credential and type
-     * TODO: Remove once LSS.setUserPasswordMetrics accepts a LockscreenCredential
-     */
-    public static LockscreenCredential createRaw(int type, byte[] credential) {
-        if (type == CREDENTIAL_TYPE_NONE) {
-            return createNone();
-        } else {
-            return new LockscreenCredential(type, PASSWORD_QUALITY_UNSPECIFIED, credential);
-        }
-    }
-
     private void ensureNotZeroized() {
         Preconditions.checkState(mCredential != null, "Credential is already zeroized");
     }
     /**
      * Returns the type of this credential. Can be one of {@link #CREDENTIAL_TYPE_NONE},
-     * {@link #CREDENTIAL_TYPE_PATTERN} or {@link #CREDENTIAL_TYPE_PASSWORD}.
-     *
-     * TODO: Remove once credential type is internal. Callers should use {@link #isNone},
-     * {@link #isPattern} and {@link #isPassword} instead.
+     * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} or
+     * {@link #CREDENTIAL_TYPE_PASSWORD}.
      */
     public int getType() {
         ensureNotZeroized();
@@ -171,14 +161,6 @@
     }
 
     /**
-     * Returns the quality type of the credential
-     */
-    public int getQuality() {
-        ensureNotZeroized();
-        return mQuality;
-    }
-
-    /**
      * Returns the credential bytes. This is a direct reference of the internal field so
      * callers should not modify it.
      *
@@ -200,9 +182,11 @@
         if (isPattern()) {
             return StorageManager.CRYPT_TYPE_PATTERN;
         }
+        if (isPin()) {
+            return StorageManager.CRYPT_TYPE_PIN;
+        }
         if (isPassword()) {
-            return mQuality == PASSWORD_QUALITY_NUMERIC
-                    ? StorageManager.CRYPT_TYPE_PIN : StorageManager.CRYPT_TYPE_PASSWORD;
+            return StorageManager.CRYPT_TYPE_PASSWORD;
         }
         throw new IllegalStateException("Unhandled credential type");
     }
@@ -219,7 +203,13 @@
         return mType == CREDENTIAL_TYPE_PATTERN;
     }
 
-    /** Returns whether this is a password credential */
+    /** Returns whether this is a numeric pin credential */
+    public boolean isPin() {
+        ensureNotZeroized();
+        return mType == CREDENTIAL_TYPE_PIN;
+    }
+
+    /** Returns whether this is an alphabetic password credential */
     public boolean isPassword() {
         ensureNotZeroized();
         return mType == CREDENTIAL_TYPE_PASSWORD;
@@ -233,7 +223,7 @@
 
     /** Create a copy of the credential */
     public LockscreenCredential duplicate() {
-        return new LockscreenCredential(mType, mQuality,
+        return new LockscreenCredential(mType,
                 mCredential != null ? Arrays.copyOf(mCredential, mCredential.length) : null);
     }
 
@@ -263,7 +253,7 @@
             }
             return;
         }
-        if (isPassword()) {
+        if (isPassword() || isPin()) {
             if (size() < LockPatternUtils.MIN_LOCK_PASSWORD_SIZE) {
                 throw new IllegalArgumentException("password must not be null and at least "
                         + "of length " + LockPatternUtils.MIN_LOCK_PASSWORD_SIZE);
@@ -272,10 +262,22 @@
         }
     }
 
+    /**
+     * Check if this credential's type matches one that's retrieved from disk. The nuance here is
+     * that the framework used to not distinguish between PIN and password, so this method will
+     * allow a PIN/Password LockscreenCredential to match against the legacy
+     * {@link #CREDENTIAL_TYPE_PASSWORD_OR_PIN} stored on disk.
+     */
+    public boolean checkAgainstStoredType(int storedCredentialType) {
+        if (storedCredentialType == CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
+            return getType() == CREDENTIAL_TYPE_PASSWORD || getType() == CREDENTIAL_TYPE_PIN;
+        }
+        return getType() == storedCredentialType;
+    }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mType);
-        dest.writeInt(mQuality);
         dest.writeByteArray(mCredential);
     }
 
@@ -284,8 +286,7 @@
 
         @Override
         public LockscreenCredential createFromParcel(Parcel source) {
-            return new LockscreenCredential(source.readInt(), source.readInt(),
-                    source.createByteArray());
+            return new LockscreenCredential(source.readInt(), source.createByteArray());
         }
 
         @Override
@@ -307,7 +308,7 @@
     @Override
     public int hashCode() {
         // Effective Java — Item 9
-        return ((17 + mType) * 31 + mQuality) * 31 + mCredential.hashCode();
+        return (17 + mType) * 31 + mCredential.hashCode();
     }
 
     @Override
@@ -315,8 +316,7 @@
         if (o == this) return true;
         if (!(o instanceof LockscreenCredential)) return false;
         final LockscreenCredential other = (LockscreenCredential) o;
-        return mType == other.mType && mQuality == other.mQuality
-                && Arrays.equals(mCredential, other.mCredential);
+        return mType == other.mType && Arrays.equals(mCredential, other.mCredential);
     }
 
     /**
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index ea0389f..b752396 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -26,6 +26,7 @@
 import android.os.Environment;
 import android.os.Process;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.storage.StorageManager;
 import android.permission.PermissionManager.SplitPermissionInfo;
 import android.text.TextUtils;
@@ -33,6 +34,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.TimingsTraceLog;
 import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -411,7 +413,13 @@
     }
 
     SystemConfig() {
-        readAllPermissions();
+        TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+        log.traceBegin("readAllPermissions");
+        try {
+            readAllPermissions();
+        } finally {
+            log.traceEnd();
+        }
     }
 
     private void readAllPermissions() {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index ce405fe..d9428c5 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -159,7 +159,6 @@
                 "android_media_AudioVolumeGroups.cpp",
                 "android_media_AudioVolumeGroupCallback.cpp",
                 "android_media_DeviceCallback.cpp",
-                "android_media_JetPlayer.cpp",
                 "android_media_MediaMetricsJNI.cpp",
                 "android_media_MicrophoneInfo.cpp",
                 "android_media_midi.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3497f92..4f7f18e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -95,7 +95,6 @@
 extern int register_android_media_AudioVolumeGroups(JNIEnv *env);
 extern int register_android_media_AudioVolumeGroupChangeHandler(JNIEnv *env);
 extern int register_android_media_MicrophoneInfo(JNIEnv *env);
-extern int register_android_media_JetPlayer(JNIEnv *env);
 extern int register_android_media_ToneGenerator(JNIEnv *env);
 extern int register_android_media_midi(JNIEnv *env);
 
@@ -1502,7 +1501,6 @@
     REG_JNI(register_android_media_AudioProductStrategies),
     REG_JNI(register_android_media_AudioVolumeGroups),
     REG_JNI(register_android_media_AudioVolumeGroupChangeHandler),
-    REG_JNI(register_android_media_JetPlayer),
     REG_JNI(register_android_media_MicrophoneInfo),
     REG_JNI(register_android_media_RemoteDisplay),
     REG_JNI(register_android_media_ToneGenerator),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 89c12f8..0487e13 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -9,6 +9,7 @@
 #include "SkColorSpace.h"
 #include "GraphicsJNI.h"
 #include "SkStream.h"
+#include "SkWebpEncoder.h"
 
 #include "android_os_Parcel.h"
 #include "android_util_Binder.h"
@@ -526,27 +527,14 @@
 enum JavaEncodeFormat {
     kJPEG_JavaEncodeFormat = 0,
     kPNG_JavaEncodeFormat = 1,
-    kWEBP_JavaEncodeFormat = 2
+    kWEBP_JavaEncodeFormat = 2,
+    kWEBP_LOSSY_JavaEncodeFormat = 3,
+    kWEBP_LOSSLESS_JavaEncodeFormat = 4,
 };
 
 static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
                                 jint format, jint quality,
                                 jobject jstream, jbyteArray jstorage) {
-    SkEncodedImageFormat fm;
-    switch (format) {
-    case kJPEG_JavaEncodeFormat:
-        fm = SkEncodedImageFormat::kJPEG;
-        break;
-    case kPNG_JavaEncodeFormat:
-        fm = SkEncodedImageFormat::kPNG;
-        break;
-    case kWEBP_JavaEncodeFormat:
-        fm = SkEncodedImageFormat::kWEBP;
-        break;
-    default:
-        return JNI_FALSE;
-    }
-
     LocalScopedBitmap bitmap(bitmapHandle);
     if (!bitmap.valid()) {
         return JNI_FALSE;
@@ -577,6 +565,30 @@
         }
         skbitmap = p3;
     }
+    SkEncodedImageFormat fm;
+    switch (format) {
+        case kJPEG_JavaEncodeFormat:
+            fm = SkEncodedImageFormat::kJPEG;
+            break;
+        case kPNG_JavaEncodeFormat:
+            fm = SkEncodedImageFormat::kPNG;
+            break;
+        case kWEBP_JavaEncodeFormat:
+            fm = SkEncodedImageFormat::kWEBP;
+            break;
+        case kWEBP_LOSSY_JavaEncodeFormat:
+        case kWEBP_LOSSLESS_JavaEncodeFormat: {
+            SkWebpEncoder::Options options;
+            options.fQuality = quality;
+            options.fCompression = format == kWEBP_LOSSY_JavaEncodeFormat ?
+                    SkWebpEncoder::Compression::kLossy : SkWebpEncoder::Compression::kLossless;
+            return SkWebpEncoder::Encode(strm.get(), skbitmap.pixmap(), options) ?
+                    JNI_TRUE : JNI_FALSE;
+        }
+        default:
+            return JNI_FALSE;
+    }
+
     return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
 }
 
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index ec91cbf..4d907f6 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -374,16 +374,17 @@
     if (scale || jsubset) {
         int translateX = 0;
         int translateY = 0;
+        SkImageInfo scaledInfo;
         if (jsubset) {
             SkIRect subset;
             GraphicsJNI::jrect_to_irect(env, jsubset, &subset);
 
-            translateX    = -subset.fLeft;
-            translateY    = -subset.fTop;
-            desiredWidth  =  subset.width();
-            desiredHeight =  subset.height();
+            translateX = -subset.fLeft;
+            translateY = -subset.fTop;
+            scaledInfo = bitmapInfo.makeWH(subset.width(), subset.height());
+        } else {
+            scaledInfo = bitmapInfo.makeWH(desiredWidth, desiredHeight);
         }
-        SkImageInfo scaledInfo = bitmapInfo.makeWH(desiredWidth, desiredHeight);
         SkBitmap scaledBm;
         if (!scaledBm.setInfo(scaledInfo)) {
             doThrowIOE(env, "Failed scaled setInfo");
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index c7b36d0..3c0971b 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -750,9 +750,11 @@
   }
 
   // May be nullptr.
-  const DynamicRefTable* dynamic_ref_table = assetmanager->GetDynamicRefTableForCookie(cookie);
+  std::shared_ptr<const DynamicRefTable> dynamic_ref_table =
+      assetmanager->GetDynamicRefTableForCookie(cookie);
 
-  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(dynamic_ref_table);
+  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(
+      std::move(dynamic_ref_table));
   status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
   asset.reset();
 
@@ -785,9 +787,11 @@
   ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie);
 
   // May be nullptr.
-  const DynamicRefTable* dynamic_ref_table = assetmanager->GetDynamicRefTableForCookie(cookie);
+   std::shared_ptr<const DynamicRefTable> dynamic_ref_table =
+       assetmanager->GetDynamicRefTableForCookie(cookie);
 
-  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(dynamic_ref_table);
+  std::unique_ptr<ResXMLTree> xml_tree = util::make_unique<ResXMLTree>(
+      std::move(dynamic_ref_table));
   status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), true);
   asset.reset();
 
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 94be61f..97dae59 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2406,6 +2406,11 @@
     // CATEGORY: SETTINGS
     // OS: Q
     SETTINGS_AWARE_DISPLAY = 1750;
+
+    // OPEN: Settings > System > Input & Gesture > tap gesture
+    // CATEGORY: SETTINGS
+    // OS: Q
+    SETTINGS_GESTURE_TAP = 1751;
     // ---- End Q Constants, all Q constants go above this line ----
     // OPEN: Settings > Network & Internet > Wi-Fi > Click new network
     // CATEGORY: SETTINGS
@@ -2426,4 +2431,9 @@
     // and under gesture navigation mode.
     DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION = 1802;
 
+    // OPEN: Settings > Security & screen lock -> Encryption & credentials > Install a certificate
+    // CATEGORY: SETTINGS
+    // OS: R
+    INSTALL_CERTIFICATE_FROM_STORAGE = 1803;
+
 }
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index a568c13..f7d4b3f 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -853,6 +853,7 @@
         optional SettingProto low_battery_sounds_enabled = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto trusted = 13;
         optional SettingProto unlock = 14;
+        optional SettingProto wireless_charging_started = 15;
     }
     optional Sounds sounds = 110;
 
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index d5528de..4ea574d 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -211,6 +211,11 @@
         optional SettingProto silence_timer_touch_count = 11 [ (android.privacy).dest =
             DEST_AUTOMATIC ];
         optional SettingProto skip_touch_count = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto aware_tap_pause_gesture_count = 13 [
+            (android.privacy).dest =
+            DEST_AUTOMATIC ];
+        optional SettingProto aware_tap_pause_touch_count = 14 [ (android.privacy).dest =
+            DEST_AUTOMATIC ];
     }
     optional Gesture gesture = 74;
 
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 15b98af..06040a5 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -43,7 +43,7 @@
     reserved 15; // next_heartbeat
     reserved 16; // last_heartbeat_time_millis
     reserved 17; // next_heartbeat_time_millis
-    optional bool in_parole = 18;
+    reserved 18; // in_parole
     optional bool in_thermal = 19;
 
     repeated int32 started_users = 2;
@@ -534,7 +534,7 @@
         option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
         optional bool is_charging = 1;
-        optional bool is_in_parole = 2;
+        reserved 2; // is_in_parole
         optional int64 elapsed_realtime = 6;
 
         // List of UIDs currently in the foreground.
diff --git a/core/proto/android/server/notificationhistory.proto b/core/proto/android/server/notificationhistory.proto
new file mode 100644
index 0000000..1e6ee3f
--- /dev/null
+++ b/core/proto/android/server/notificationhistory.proto
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+package com.android.server.notification;
+
+import "frameworks/base/core/proto/android/server/enums.proto";
+
+option java_multiple_files = true;
+
+// On disk data store for historical notifications
+message NotificationHistoryProto {
+  message StringPool {
+    optional int32 size = 1;
+    repeated string strings = 2;
+  }
+
+  message Notification {
+    // The package that posted the notification
+    optional string package = 1;
+    // package_index contains the index + 1 of the package name in the string pool
+    optional int32 package_index = 2;
+
+    // The name of the NotificationChannel this notification was posted to
+    optional string channel_name = 3;
+    // channel_name_index contains the index + 1 of the channel name in the string pool
+    optional int32 channel_name_index = 4;
+
+    // The id of the NotificationChannel this notification was posted to
+    optional string channel_id = 5;
+    // channel_id_index contains the index + 1 of the channel id in the string pool
+    optional int32 channel_id_index = 6;
+
+    // The uid of the package that posted the notification
+    optional int32 uid = 7;
+    // The user id that the notification was posted to
+    optional int32 user_id = 8;
+    // The time at which the notification was posted
+    optional int64 posted_time_ms = 9;
+    // The title of the notification
+    optional string title = 10;
+    // The text of the notification
+    optional string text = 11;
+    // The small icon of the notification
+    optional Icon icon = 12;
+
+    // Matches the constants of android.graphics.drawable.Icon
+    enum ImageTypeEnum {
+      TYPE_UNKNOWN = 0;
+      TYPE_BITMAP = 1;
+      TYPE_RESOURCE = 2;
+      TYPE_DATA = 3;
+      TYPE_URI = 4;
+      TYPE_ADAPTIVE_BITMAP = 5;
+    }
+
+    message Icon {
+      optional ImageTypeEnum image_type = 1;
+      optional string image_bitmap_filename = 2;
+      optional int32 image_resource_id = 3;
+      optional string image_resource_id_package = 4;
+      optional bytes image_data = 5;
+      optional int32 image_data_length = 6;
+      optional int32 image_data_offset = 7;
+      optional string image_uri = 8;
+    }
+  }
+
+  // Pool of strings to save space
+  optional StringPool string_pool = 1;
+  // Versioning fields
+  optional int32 major_version = 2;
+
+  // List of historical notifications
+  repeated Notification notification = 3;
+}
diff --git a/core/proto/android/server/usagestatsservice.proto b/core/proto/android/server/usagestatsservice.proto
index 75f265e..f26eefa 100644
--- a/core/proto/android/server/usagestatsservice.proto
+++ b/core/proto/android/server/usagestatsservice.proto
@@ -114,6 +114,4 @@
   repeated UsageStats packages = 20;
   repeated Configuration configurations = 21;
   repeated Event event_log = 22;
-
-  repeated Event pending_events = 23; // TODO: move to usagestatsservice_v2.proto
 }
diff --git a/core/proto/android/server/usagestatsservice_v2.proto b/core/proto/android/server/usagestatsservice_v2.proto
new file mode 100644
index 0000000..a28fcf3
--- /dev/null
+++ b/core/proto/android/server/usagestatsservice_v2.proto
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+package com.android.server.usage;
+import "frameworks/base/core/proto/android/content/configuration.proto";
+import "frameworks/base/core/proto/android/privacy.proto";
+
+option java_multiple_files = true;
+
+/**
+ * Obfuscated version of android.service.IntervalStatsProto (usagestatsservice.proto).
+ */
+message IntervalStatsObfuscatedProto {
+
+  message CountAndTime {
+    optional int32 count = 1;
+    optional int64 time_ms = 2;
+  }
+
+  // Stores the relevant information an IntervalStats will have about a Configuration
+  message Configuration {
+    optional .android.content.ConfigurationProto config = 1;
+    optional int64 last_time_active_ms = 2;
+    optional int64 total_time_active_ms = 3;
+    optional int32 count = 4;
+    optional bool active = 5;
+  }
+
+  // The following fields contain supplemental data used to build IntervalStats.
+  optional int64 end_time_ms = 1;
+  optional int32 major_version = 2;
+  optional int32 minor_version = 3;
+
+  // The following fields contain aggregated usage stats data
+  optional CountAndTime interactive = 10;
+  optional CountAndTime non_interactive = 11;
+  optional CountAndTime keyguard_shown = 12;
+  optional CountAndTime keyguard_hidden = 13;
+
+  // The following fields contain listed usage stats data
+  repeated UsageStatsObfuscatedProto packages = 20;
+  repeated Configuration configurations = 21;
+  repeated EventObfuscatedProto event_log = 22;
+  // The following field is only used to persist the reported events before a user unlock
+  repeated PendingEventProto pending_events = 23;
+}
+
+/**
+ * Stores the relevant information from an obfuscated UsageStats.
+ */
+message UsageStatsObfuscatedProto {
+  message ChooserAction {
+    message CategoryCount {
+      optional int32 category_token = 1;
+      optional int32 count = 2;
+    }
+    optional int32 action_token = 1;
+    repeated CategoryCount counts = 2;
+  }
+  optional int32 package_token = 1;
+  optional int64 last_time_active_ms = 3;
+  optional int64 total_time_active_ms = 4;
+  optional int32 last_event = 5;
+  optional int32 app_launch_count = 6;
+  repeated ChooserAction chooser_actions = 7;
+  optional int64 last_time_service_used_ms = 8;
+  optional int64 total_time_service_used_ms = 9;
+  optional int64 last_time_visible_ms = 10;
+  optional int64 total_time_visible_ms = 11;
+}
+
+/**
+ * Stores the relevant information from an obfuscated Event.
+ */
+message EventObfuscatedProto {
+  optional int32 package_token = 1;
+  optional int32 class_token = 2;
+  optional int64 time_ms = 3;
+  optional int32 flags = 4;
+  optional int32 type = 5;
+  optional .android.content.ConfigurationProto config = 6;
+  optional int32 shortcut_id_token = 7;
+  optional int32 standby_bucket = 8;
+  optional int32 notification_channel_id_token = 9;
+  optional int32 instance_id = 10;
+  optional int32 task_root_package_token = 11;
+  optional int32 task_root_class_token = 12;
+}
+
+/**
+ * This message stores all of the fields in an Event object as strings instead of tokens.
+ */
+message PendingEventProto {
+  optional string package_name = 1;
+  optional string class_name = 2;
+  optional int64 time_ms = 3;
+  optional int32 flags = 4;
+  optional int32 type = 5;
+  optional .android.content.ConfigurationProto config = 6;
+  optional string shortcut_id = 7;
+  optional int32 standby_bucket = 8;
+  optional string notification_channel_id = 9;
+  optional int32 instance_id = 10;
+  optional string task_root_package = 11;
+  optional string task_root_class = 12;
+}
+
+/**
+ * A proto message representing the obfuscated tokens mappings for Usage Stats.
+ */
+message ObfuscatedPackagesProto {
+  message PackagesMap {
+    optional int32 package_token = 1;
+    // The list of strings for each package where their indices are the token
+    repeated string strings = 2;
+  }
+
+  optional int32 counter = 1;
+  // Stores the mappings for every package
+  repeated PackagesMap packages_map = 2;
+}
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
index 2e1de79..40c5a85 100644
--- a/core/proto/android/service/usb.proto
+++ b/core/proto/android/service/usb.proto
@@ -32,6 +32,7 @@
     optional UsbPortManagerProto port_manager = 3;
     optional UsbAlsaManagerProto alsa_manager = 4;
     optional UsbSettingsManagerProto settings_manager = 5;
+    optional UsbPermissionsManagerProto permissions_manager = 6;
 }
 
 message UsbDeviceManagerProto {
@@ -309,26 +310,12 @@
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional int32 user_id = 1;
-    repeated UsbSettingsDevicePermissionProto device_permissions = 2;
-    repeated UsbSettingsAccessoryPermissionProto accessory_permissions = 3;
+    reserved 2; // previously device_permissions, now unused
+    reserved 3; // previously accessory_permissions, now unused
     repeated UsbDeviceAttachedActivities device_attached_activities = 4;
     repeated UsbAccessoryAttachedActivities accessory_attached_activities = 5;
 }
 
-message UsbSettingsDevicePermissionProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    optional string device_name = 1;
-    repeated int32 uids = 2;
-}
-
-message UsbSettingsAccessoryPermissionProto {
-    option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    optional string accessory_description = 1;
-    repeated int32 uids = 2;
-}
-
 message UsbProfileGroupSettingsManagerProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -345,6 +332,63 @@
     optional UserPackageProto user_package = 2;
 }
 
+message UsbPermissionsManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    repeated UsbUserPermissionsManagerProto user_permissions = 1;
+}
+
+message UsbUserPermissionsManagerProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 user_id = 1;
+
+    repeated UsbDevicePermissionProto device_permissions = 2;
+    repeated UsbAccessoryPermissionProto accessory_permissions = 3;
+
+    repeated UsbDevicePersistentPermissionProto device_persistent_permissions = 4;
+    repeated UsbAccessoryPersistentPermissionProto accessory_persistent_permissions = 5;
+}
+
+message UsbDevicePermissionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Name of device set by manufacturer
+    // All devices of the same model have the same name
+    optional string device_name = 1;
+    repeated int32 uids = 2;
+}
+
+message UsbAccessoryPermissionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Description of accessory set by manufacturer
+    // All accessories of the same model have the same description
+    optional string accessory_description = 1;
+    repeated int32 uids = 2;
+}
+
+message UsbDevicePersistentPermissionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbDeviceFilterProto device_filter = 1;
+    repeated UsbUidPermissionProto permission_values = 2;
+}
+
+message UsbAccessoryPersistentPermissionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional UsbAccessoryFilterProto accessory_filter = 1;
+    repeated UsbUidPermissionProto permission_values = 2;
+}
+
+message UsbUidPermissionProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 uid = 1;
+    optional bool is_granted = 2;
+}
+
 message UsbDeviceFilterProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f98ea2c..c365aae 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2274,7 +2274,7 @@
          types of interactions
          @hide -->
     <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
-        android:protectionLevel="signature|installer" />
+        android:protectionLevel="signature|installer|telephony" />
 
     <!-- @SystemApi Allows an application to start its own activities, but on a different profile
          associated with the user. For example, an application running on the main profile of a user
@@ -2904,8 +2904,9 @@
 
     <!-- Allows an application to be the status bar.  Currently used only by SystemUI.apk
     @hide -->
+    // TODO: remove telephony once decouple settings activity from phone process
     <permission android:name="android.permission.STATUS_BAR_SERVICE"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony" />
 
     <!-- Allows an application to bind to third party quick settings tiles.
          <p>Should only be requested by the System, should be required by
@@ -3032,7 +3033,7 @@
          @hide
     -->
     <permission android:name="android.permission.SET_ACTIVITY_WATCHER"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|telephony" />
 
     <!-- @SystemApi Allows an application to call the activity manager shutdown() API
          to put the higher-level system there into a shutdown state.
@@ -3536,7 +3537,7 @@
     <!-- @SystemApi Allows an application to manage the holders of a role.
          @hide -->
     <permission android:name="android.permission.MANAGE_ROLE_HOLDERS"
-                android:protectionLevel="signature|installer" />
+                android:protectionLevel="signature|installer|telephony" />
 
     <!-- @SystemApi Allows an application to observe role holder changes.
          @hide -->
@@ -4569,7 +4570,7 @@
     <!-- @hide Permission that allows configuring appops.
      <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MANAGE_APPOPS"
-                android:protectionLevel="signature" />
+                android:protectionLevel="signature|telephony" />
 
     <!-- @hide Permission that allows background clipboard access.
          <p>Not for use by third-party applications. -->
@@ -4951,6 +4952,14 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name="com.android.server.updates.EmergencyNumberDbInstallReceiver"
+                  android:permission="android.permission.UPDATE_CONFIG">
+            <intent-filter>
+                <action android:name="android.os.action.UPDATE_EMERGENCY_NUMBER_DB" />
+                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+            </intent-filter>
+        </receiver>
+
         <receiver android:name="com.android.server.MasterClearReceiver"
             android:permission="android.permission.MASTER_CLEAR">
             <intent-filter
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index dd9eafe..4ca0df4 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -295,7 +295,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om SMS\'e te stuur en te bekyk?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Berging"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"toegang te verkry tot foto\'s, media en lêers op jou toestel"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou foto\'s, media en lêers op jou toestel?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"Gee vir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou foto\'s, media en lêers op jou toestel?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"oudio op te neem"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om oudio op te neem?"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Laat die program toe om SMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is, kan monitor of uitvee, sonder dat jy dit gesien het."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ontvang teksboodskappe (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Laat die program toe om MMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is kan monitor of uitvee, sonder dat jy dit gesien het."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Stuur seluitsendingboodskappe aan"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Laat die program toe om die seluitsendingmodule te bind om seluitsendingboodskappe aan te stuur wanneer hulle ontvang word. Seluitsendingwaarskuwings word in sommige liggings gelewer om jou oor noodsituasies te waarsku. Kwaadwillige programme kan met die werkverrigting of werking van jou toestel inmeng wanneer \'n noodseluitsending ontvang word."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lees seluitsending-boodskappe"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Laat die program toe om seluitsending-boodskappe te lees wat deur jou toestel ontvang word. Seluitsending-waarskuwings word in sommige plekke afgelewer om jou van noodsituasies te waarsku. Kwaadwillige programme mag inmeng met die prestasie of die werking van jou toestel wanneer \'n noodgeval se seluitsending ontvang word."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lees ingetekende nuus"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Laat die program toe om Moenie Steur Nie-opstelling te lees en skryf."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"begin kyk van toestemminggebruik"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Laat die houer toe om die toestemminggebruik vir \'n program te begin. Behoort nooit vir normale programme nodig te wees nie."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"toeganklikheidkortpadteiken"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Laat \'n program toe om die toeganklikheidkortpadteiken te definieer."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Beheer die lengte en die karakters wat in skermslotwagwoorde en -PIN\'e toegelaat word."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor pogings om skerm te ontsluit"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index a007c9d..eb5265e 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"መተግበሪያው የኤስ.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"የፅሁፍ መልዕክቶችን ተቀበል (ኤም.ኤም.ኤስ.)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"መተግበሪያው የኤም.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"የሕዋስ ስርጭት መልዕክቶችን ማስተላለፍ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"የሕዋስ ስርጭት መልዕክቶች እንደመጡ ለማስተላለፍ መተግበሪያው ከሕዋስ ስርጭት ሞዱሉ ጋር እንዲተሳሰር ያስችለዋል። የሕዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የሕዋስ ስርጭት ሲደርስ ተንኮል-አዘል መተግበሪያዎች በመሣሪያዎ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"የህዋስ ስርጭት መልዕክቶችን አንብብ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"መሣሪያህ የህዋስ ስርጭት መልዕክቶች ሲቀበል መተግበሪያው እንዲያነበው ይፈቅድለታል። የህዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የህዋስ ስርጭት ሲደርስ ተንኮል አዘል መተግበሪያዎች በመሣሪያህ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"የምዝገባ መግቦች አንበብ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"መተግበሪያው የአትረብሽ ውቅረትን እንዲያነብብ እና እንዲጸፍ ይፈቅዳል።"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"የእይታ ፈቃድ መጠቀምን መጀመር"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ያዢው ለአንድ መተግበሪያ የፈቃድ አጠቃቀሙን እንዲያስጀምር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"የተደራሽነት አቋራጭ ዒላማ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"መተግበሪያ የተደራሽነት አቋራጭ ዒላማን ለመግለጽ እንዲችል ይፈቅድለታል።"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"በማያ ገጽ መቆለፊያ የይለፍ ቃሎች እና ፒኖች ውስጥ የሚፈቀዱ ቁምፊዎችን እና ርዝመታቸውን ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"የማሳያ-ክፈት ሙከራዎችን ክትትል ያድርጉባቸው"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 2e272ee..c9067e5 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -356,10 +356,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏للسماح للتطبيق بتلقي ومعالجة الرسائل القصيرة SMS. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها إلى جهازك أو حذفها بدون عرضها لك."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"تلقي رسائل نصية (رسائل وسائط متعددة)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"للسماح للتطبيق بتلقي ومعالجة رسائل الوسائط المتعددة. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها لجهازك أو حذفها بدون عرضها لك."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"إعادة توجيه رسائل البث الخلوي"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"يسمح للتطبيق بالارتباط بوحدة البث الخلوي لإعادة توجيه رسائل البث الخلوي بينما يتم استقبالها. ويتم تسليم تنبيهات البث الخلوي في بعض المواقع لتحذيرك في حالات الطوارئ. ويمكن أن تؤثر التطبيقات الضارة على أداء الجهاز أو تشغيله عندما يتم تلقي بث خلوي في حالات الطوارئ."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"قراءة رسائل بث الخلية"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم اشعارات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"قراءة الخلاصات المشتركة"</string>
@@ -530,7 +528,7 @@
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"للسماح للتطبيق باستخدام الأجهزة البيومترية للمصادقة"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"لإدارة أجهزة بصمة الإصبع"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"للسماح للتطبيق باستدعاء طرق لإضافة نماذج من بصمات الأصابع وحذفها."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"لاستخدام أجهزة بصمة الإصبع"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"استخدام أجهزة بصمة الإصبع"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"للسماح للتطبيق باستخدام أجهزة بصمة الإصبع للمصادقة"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"تعديل مجموعتك الموسيقية"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"للسماح للتطبيق بتعديل مجموعتك الموسيقية."</string>
@@ -671,8 +669,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"للسماح للتطبيق بقراءة تهيئة \"عدم الإزعاج\" وكتابتها."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"بدء استخدام إذن العرض"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"للسماح للمالك ببدء استخدام الإذن لأحد التطبيقات. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"هدف اختصار أدوات تمكين الوصول"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"للسماح للتطبيق بتحديد هدف اختصار أدوات تمكين الوصول."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"للتحكم في الطول والأحرف المسموح بها في كلمات المرور وأرقام التعريف الشخصي في قفل الشاشة."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -1679,8 +1675,8 @@
     <string name="expires_on" msgid="3676242949915959821">"تنتهي الصلاحية في:"</string>
     <string name="serial_number" msgid="758814067660862493">"الرقم المسلسل:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"بصمات الأصابع:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"‏بصمة أصبع SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"‏بصمة أصبع SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"‏بصمة إصبع SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"‏بصمة إصبع SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"عرض الكل"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"اختيار نشاط"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"مشاركة مع"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 70d9713..7a89b65 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"এপটোক এছএমএছ বাৰ্তাবোৰ পাবলৈ আৰু প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ অনুমতি দিয়ে৷ ইয়াৰ অৰ্থ এইটোৱেই যে এপটোৱে আপোনাক বাৰ্তাবোৰ নেদেখুৱাকৈয়ে আপোনাৰ ডিভাইচলৈ পঠিওৱা বাৰ্তাবোৰ নিৰীক্ষণ কৰিব বা মচিব পাৰে৷"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"পাঠ বার্তা (এমএমএছ) বোৰ লাভ কৰক"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"এমএমএছ বার্তাবোৰ লাভ আৰু ইয়াৰ প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াৰ অৰ্থ হৈছে এই এপে আপোনাৰ ডিভাইচলৈ প্ৰেৰণ কৰা বার্তাসমূহ আপোনাক নেদেখুৱাকৈয়ে পৰ্যবেক্ষণ আৰু মচিব পাৰে।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ ফৰৱাৰ্ড কৰক"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ লাভ কৰিলে সেইবোৰ ফৰৱাৰ্ড কৰিবলৈ এপ্‌টোক চেল সম্প্ৰচাৰ মডিউলটোৰ সৈতে সংযুক্ত হ\'বলৈ অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিসমূহৰ বিষয়ে সতৰ্ক কৰিবলৈ কিছুমান অৱস্থানত চেল সম্প্ৰচাৰ সতৰ্কবাৰ্তাসমূহ ডেলিভাৰ কৰা হয়। কোনো জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰিলে ক্ষতিকাৰক এপ্‌সমূহে আপোনাৰ ডিভাইচটোৰ কাৰ্যক্ষমতা অথবা কাৰ্যপ্ৰণালীত হস্তক্ষেপ কৰিব পাৰে।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়ক"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপোনাৰ ডিভাইচে লাভ কৰা চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিবোৰত সর্তক কৰিবলৈ চেল সম্প্ৰচাৰৰ বার্তাবোৰ প্ৰেৰণ কৰা হয়। জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা বা কাৰ্যপ্ৰণালীত ক্ষতিকাৰক এপবোৰে হস্তক্ষেপ কৰিব পাৰে।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"আপুনি সদস্যভুক্ত হোৱা ফীডসমূহ পঢ়ক"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"অসুবিধা নিদিবৰ কনফিগাৰেশ্বনক পঢ়িবলৈ আৰু সালসলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"চোৱাৰ অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰক"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ধাৰকক কোনো এপৰ বাবে অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰিবলৈ দিয়ে। সাধাৰণ এপ্‌সমূহৰ বাবে কেতিয়াও প্ৰয়োজন হ’ব নালাগে।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"সাধ্য সুবিধাসমূহৰ শ্বৰ্টকাট লক্ষ্য"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"সাধ্য সুবিধাসমূহৰ শ্বৰ্টকাট লক্ষ্য নির্ধাৰণ কৰিবলৈ এটা এপক অনুমতি দিয়ে।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"পাছৱর্ডৰ নিয়ম ছেট কৰক"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"স্ক্ৰীণ লক পাছৱৰ্ড আৰু পিনৰ দৈর্ঘ্য আৰু কি কি আখৰ ব্যৱহাৰ কৰিব পাৰে তাক নিয়ন্ত্ৰণ কৰক।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"স্ক্ৰীণ আনলক কৰা প্ৰয়াসবোৰ পৰ্যবেক্ষণ কৰিব পাৰে"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 5d09250..21dbf03 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tətbiqə MMS mesajlarını almaq və emal etmək icazəsi verir. Bu o deməkdir ki, tətbiq sizin mesajlarınızı sizə göstərmədən monitorinq edə və ya silə bilər."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"mətn mesajlarını qəbul edir (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Tətbiqə MMS mesajlarını qəbul və emal üçün imkan verir. Bu o deməkdir ki, bu tətbiq sizə göstərmədən cihazınıza göndərilən mesajları silə bilər."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Şəbəkə yayımı mesajlarını yönləndirin"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tətbiqə şəbəkə yayım mesajlarını əldə edildiyi anda yönləndirmək üçün şəbəkə yayımı moduluna bağlanmaq icazəsi verir. Şəbəkə yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı Sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər fövqəladə şəbəkə yayımı əldə edildiyi zaman cihazın performansına və əməliyyatına müdaxilə edə bilər."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"mobil yayım mesajlarını oxuyur"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tətbiqə telefonunuz tərəfindən alınmış yayım mesajlarını oxuma icazəsi verir. Telefon yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər təcili mobil yayım qəbul edildiyi zaman telefonunun performansına və əməliyyatına müdaxilə edə bilər."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"abunə olunmuş xəbərləri oxuyur"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Tanınmır"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Doğrulama ləğv edildi"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Pin, nümunə və ya parol ayarlanmayıb"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmaq qismən müəyyən olundu. Lütfən, yenidən cəhd edin."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmaq izi yarımçıq müəyyən olundu. Lütfən, yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmaq izi tanınmadı. Lütfən, yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Barmaq izi sensoru çirklidir. Lütfən, təmizləyin və yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Barmağı çox tez tərpətdiniz. Yenidən edin."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Tətbiqə \"Narahat Etməyin\" konfiqurasiyasını oxumağa və yazmağa icazə verin."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Baxış icazəsinin istifadəsinə başlayın"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Sahibinə tətbiqin icazədən istifadəsinə başlamağa imkan verir. Adi tətbiqlər üçün heç vaxt tələb edilmir."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"əlçatımlılıq qısayolunun hədəfi"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tətbiqə əlçatımlılıq qısayolunun hədəfini müəyyən etməyə imkan verir."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parol qaydalarını təyin edin"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran kilidinin parolu və PINlərində icazə verilən uzunluq və simvollara nəzarət edin."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekranı kiliddən çıxarmaq üçün edilən cəhdlərə nəzarət edin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 5891bae..dbb788d 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Dozvoljava aplikaciji da prima i obrađuje SMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prijem tekstualnih poruka (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Dozvoljava aplikaciji da prima i obrađuje MMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Prosleđivanje poruka za mobilne uređaje na lokalitetu"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Dozvoljava aplikaciji da se vezuje za modul poruka za mobilne uređaje na lokalitetu da bi prosleđivala poruke za mobilne uređaje na lokalitetu onako kako su primljene. Obaveštenja poruka za mobilne uređaje na lokalitetu se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju rad uređaja kada se primi poruka o hitnom slučaju za mobilne uređaje na lokalitetu."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čitanje poruka info servisa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogućava aplikaciji da čita poruke info servisa koje uređaj prima. Upozorenja info servisa se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju funkcionisanje uređaja kada se primi poruka info servisa o hitnom slučaju."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čitanje prijavljenih fidova"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Dozvoljava aplikaciji da čita i upisuje konfiguraciju podešavanja Ne uznemiravaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"početak korišćenja dozvole za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Dozvoljava vlasniku da započne korišćenje dozvole za aplikaciju. Nikada ne bi trebalo da bude potrebna za uobičajene aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj prečice za pristupačnost"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Dozvoljava aplikaciji da definiše cilj prečice za pristupačnost."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Podešavanje pravila za lozinku"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontroliše dužinu i znakove dozvoljene u lozinkama i PIN-ovima za zaključavanje ekrana."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Nadgledajte pokušaje otključavanja ekrana"</string>
@@ -1610,8 +1606,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Ističe:"</string>
     <string name="serial_number" msgid="758814067660862493">"Serijski broj:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Digitalni otisci:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 digitalni otisak:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 digitalni otisak:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 otisak prsta:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 otisak prsta:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Prikaži sve"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Izbor aktivnosti"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Deli sa"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 6fdc8f1..bae2640 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -330,7 +330,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Кіраваць маштабам дысплэя і пазіцыянаваннем."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Выконваць жэсты"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна кранаць, праводзіць пальцам, маштабаваць шчыпком, а таксама выконваць іншыя жэсты."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жэсты адбіткаў пальцаў"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жэсты на сканеры адбіткаў пальцаў"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"адключаць ці змяняць радок стану"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дазваляе прыкладанням атрымліваць і апрацоўваць SMS-паведамленні. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"атрыманне тэкставых паведамленняў (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Дазваляе прыкладанням атрымліваць і апрацоўваць MMS-паведамленнi. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Пераадрасоўваць паведамленні сотавай трансляцыі"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дазваляе праграме звязвацца з модулем сотавай трансляцыі, каб пераадрасоўваць атрыманыя там паведамленні. Абвесткі сотавай трансляцыі дасылаюцца ў некаторыя месцы, каб папярэджваць вас пра надзвычайныя сітуацыі. Шкодныя праграмы могуць негатыўна ўплываць на прадукцыйнасць або працу прылады падчас атрымання паведамленняў сотавай трансляцыі пра надзвычайныя сітуацыі."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"чытаць паведамленні базавай станцыі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Дазваляе прыкладанню чытаць паведамленні базавай станцыі, атрыманыя прыладай. Папярэджанні базавай станцыі дасылаюцца ў некаторыя месцы, каб папярэдзіць вас аб надзвычайных сітуацыях. Шкоднасныя прыкладанні могуць уплываць на прадукцыйнасць ці працу прылады пры атрыманні паведамлення базавай станцыі аб надзвычайнай сітуацыі."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"чытаць падпісаныя каналы"</string>
@@ -540,7 +538,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не распазнана"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Аўтэнтыфікацыя скасавана"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Не заданы PIN-код, узор разблакіроўкі або пароль"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Выяўлена частка адбіткаў пальцаў. Паспрабуйце яшчэ раз."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Не ўвесь адбітак пальца адсканіраваны. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не атрымалася апрацаваць адбітак пальца. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчык адбіткаў пальцаў брудны. Ачысціце яго і паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Палец рухаўся занадта хутка. Паспрабуйце яшчэ раз."</string>
@@ -551,12 +549,12 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Твар распазнаны"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Твар распазнаны. Націсніце, каб пацвердзіць"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратныя сродкі адбіткаў пальцаў недаступныя."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Адбіткі пальцаў нельга захаваць. Выдаліце існы адбітак."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання адбіткаў пальцаў выйшаў. Паспрабуйце яшчэ раз."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Адбіткі пальцаў нельга захаваць. Выдаліце існуючы адбітак."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання выйшаў. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Аперацыя з адбіткамі пальцаў скасавана."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Аўтэнтыфікацыя па адбітках пальцаў скасавана карыстальнікам."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Занадта шмат спроб. Сканер адбіткаў пальцаў адключаны."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Занадта шмат спроб. Сканер адбіткаў пальцаў выключаны."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Адбіткі пальцаў не зарэгістраваны."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"На гэтай прыладзе няма сканера адбіткаў пальцаў."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Дазваляе праграме чытаць і выконваць запіс у канфігурацыю рэжыму «Не турбаваць»."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"запусціць выкарыстанне дазволаў на прагляд"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Дазваляе трымальніку запусціць выкарыстанне дазволаў праграмай. Не патрэбна для звычайных праграм."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Аб\'екты хуткага доступу да спецыяльных магчымасцей"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Праграма зможа вызначаць аб\'екты хуткага доступу да спецыяльных магчымасцей."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устанавіць правілы паролю"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Кіраваць даўжынёй і сімваламі, дазволенымі пры ўводзе пароляў і PIN-кодаў блакіроўкі экрана."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Сачыць за спробамі разблакіроўкі экрана"</string>
@@ -1633,7 +1629,7 @@
     <string name="expires_on" msgid="3676242949915959821">"Заканчваецца:"</string>
     <string name="serial_number" msgid="758814067660862493">"Серыйны нумар:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Адбіткі пальцаў:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Адбітак пальцаў SHA-256:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Адбітак SHA-256:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"Адбіткі пальцаў SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Прагледзець усё"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Выберыце працэс"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index e5fb7e8..e7b3090 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Разрешава на приложението да получава и обработва SMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"получаване на текстови съобщения (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Разрешава на приложението да получава и обработва MMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Препращане на съобщения с клетъчно излъчване"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Разрешава на приложението да се обвърже с модула за клетъчно излъчване, за да препраща получените съобщения с клетъчно излъчване. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни случаи. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"четене на съобщения с клетъчно излъчване"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Разрешава на приложението да чете съобщения с клетъчно излъчване, получени от устройството ви. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни ситуации. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"четене на емисиите с абонамент"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Предоставя на приложението достъп за четене и запис до конфигурацията на „Не безпокойте“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"стартиране на прегледа на използваните разрешения"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Разрешава на притежателя да стартира прегледа на използваните разрешения за дадено приложение. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"цел на прекия път към функцията за достъпност"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Разрешава на приложението да определя целта на прекия път към функцията за достъпност."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролира дължината и разрешените знаци за паролите и ПИН кодовете за заключване на екрана."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1587,8 +1583,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Изтича на:"</string>
     <string name="serial_number" msgid="758814067660862493">"Сериен номер:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Пръстови отпечатъци:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Пръстов отпечатък SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Пръстов отпечатък SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Отпечатък SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Отпечатък SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Вижте всички"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Избор на активност"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Споделяне със:"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 651ed4d..beb08b2 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -283,7 +283,7 @@
     <string name="permgrouprequest_contacts" msgid="6032805601881764300">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার পরিচিতিতে অ্যাক্সেস দেবেন?"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"লোকেশন"</string>
     <string name="permgroupdesc_location" msgid="1346617465127855033">"এই ডিভাইসের লোকেশন অ্যাক্সেস"</string>
-    <string name="permgrouprequest_location" msgid="3788275734953323491">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে এই ডিভাইসের লোকেশন অ্যাক্সেস করতে দেবেন?"</string>
+    <string name="permgrouprequest_location" msgid="3788275734953323491">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে এই ডিভাইসের লোকেশন অ্যাক্সেস করতে দেবেন?"</string>
     <string name="permgrouprequestdetail_location" msgid="1347189607421252902">"আপনি এই অ্যাপ ব্যবহার করার সময়েই শুধু সেটি আপনার লোকেশন অ্যাক্সেস করতে পারবে"</string>
     <string name="permgroupbackgroundrequest_location" msgid="5039063878675613235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে এই ডিভাইসের লোকেশন &lt;b&gt;সব সময়&lt;/b&gt; অ্যাক্সেস করার অনুমতি দিতে চান?"</string>
     <string name="permgroupbackgroundrequestdetail_location" msgid="4597006851453417387">"আপনি যখন অ্যাপটি ব্যবহার করবেন শুধুমাত্র তখনই অ্যাপটি বর্তমান লোকেশন অ্যাক্সেস করতে পারবে।"</string>
@@ -298,7 +298,7 @@
     <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার ডিভাইসের ফটো, মিডিয়া এবং ফাইলে অ্যাক্সেস দেবেন?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"মাইক্রোফোন"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"অডিও রেকর্ড"</string>
-    <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে অডিও রেকর্ড করতে দেবেন?"</string>
+    <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে অডিও রেকর্ড করতে দেবেন?"</string>
     <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"শারীরিক অ্যাক্টিভিটি"</string>
     <string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"শারীরিক অ্যাক্টিভিটি অ্যাক্সেস করা"</string>
     <string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার শারীরিক অ্যাক্টিভিটি অ্যাক্সেস করার অনুমতি দিতে চান?"</string>
@@ -324,7 +324,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"প্রদর্শনের জুমের স্তর এবং লোকেশন নির্ধারন নিয়ন্ত্রণ করুন৷"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"অঙ্গভঙ্গির কাজগুলি সম্পাদন"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"আলতো চাপ দেওয়া, সোয়াইপ, পিঞ্চ করা এবং অন্যান্য ইঙ্গিতের কাজগুলি সম্পাদন করতে পারবেন৷"</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ফিঙ্গারপ্রিন্ট সেন্সরের উপর করা অঙ্গভঙ্গিগুলি"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"আঙ্গুলের ছাপ সেন্সরের উপর করা জেসচার"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ডিভাইসের আঙ্গুলের ছাপের সেন্সরের উপরে ইঙ্গিত করলে বুঝতে পারে।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"স্ট্যাটাস বার নিষ্ক্রিয় অথবা সংশোধন করে"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"অ্যাপ্লিকেশনকে স্ট্যাটাস বার অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে এসএমএস প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"টেক্সট মেসেজ পান (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"অ্যাপ্লিকেশানটিকে MMS মেসেজ প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো মেসেজগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"সেল ব্রডকাস্টের মাধ্যমে মেসেজ ফরওয়ার্ড করুন"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"সেল ব্রডকাস্ট মেসেজ পেলে এটি সেল ব্রডকাস্ট মডিউলের সাথে তা যুক্ত করে যাতে সেই মেসেজ ফরওয়ার্ড করা যায়। আপনাকে জরুরি অবস্থা সম্পর্কে সাবধান করতে কিছু লোকেশনে সেল ব্রডকাস্ট অ্যালার্ট মেসেজ ডেলিভার করা হয়। জরুরি সেল ব্রডকাস্ট পাওয়া গেলে ক্ষতিকারক অ্যাপ আপনার ডিভাইসের পারফর্ম্যান্স ও অপারেশনে বাধা সৃষ্টি করতে পারে।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"সেল সম্প্রচার মেসেজ পড়ুন"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপনার ডিভাইস দ্বারা প্রাপ্ত সেল সম্প্রচার পড়তে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ কয়েকটি স্থানে আপনাকে জরুরি অবস্থার জন্য সতর্ক করতে জরুরি সতর্কতাগুলি বিতরণ করা হয়৷ যখন একটি জরুরি সেল সম্প্রচার প্রাপ্ত হয় তখন ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার ডিভাইসের কার্য সম্পাদনা বা কার্যকলাপে প্রতিবন্ধকতার সৃষ্টি করতে পারে৷"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"গ্রাহক হিসেবে নেওয়া ফিডগুলি পড়ে"</string>
@@ -553,7 +551,7 @@
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"বহুবার চেষ্টা করেছেন। আঙ্গুলের ছাপ নেওয়ার সেন্সর অক্ষম করা হয়েছে।"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"কোনও আঙ্গুলের ছাপ নথিভুক্ত করা হয়নি।"</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"এই ডিভাইসে ফিঙ্গারপ্রিন্ট সেন্সর নেই।"</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"এই ডিভাইসে আঙ্গুলের ছাপ নেওয়ার সেন্সর নেই।"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"আঙ্গুল <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"অ্যাপটিকে \'বিরক্ত করবে না\' কনফিগারেশন পড়া এবং লেখার অনুমতি দেয়।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"দেখার অনুমতি কাজে লাগানো শুরু করুন"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"কোনও অ্যাপের কোনও নির্দিষ্ট অনুমতির ব্যবহার শুরু করার ক্ষেত্রে হোল্ডারকে সাহায্য করে। সাধারণ অ্যাপের জন্য এটির পরিবর্তন হওয়ার কথা নয়।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"অ্যাক্সেসিবিলিটির শর্টকাটের টার্গেট"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"এটি একটি অ্যাপকে অ্যাক্সেসিবিলিটির শর্টকাটের টার্গেটকে ব্যাখ্যা করতে অনুমতি দেয়।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"পাসওয়ার্ড নিয়মগুলি সেট করে"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"স্ক্রিন লক করার পাসওয়ার্ডগুলিতে অনুমতিপ্রাপ্ত অক্ষর এবং দৈর্ঘ্য নিয়ন্ত্রণ করে৷"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"স্ক্রিন আনলক করার প্রচেষ্টাগুলির উপরে নজর রাখুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 0695fb8..862beee 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Omogućava aplikaciji primanje i obradu SMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primanje tekstualnih poruka (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Omogućava aplikaciji prijem i obradu MMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Prosljeđivanje poruka info servisa"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Dopušta aplikaciji da se veže za modul info servisa kako bi prosljeđivala poruke info servisa. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informacije o vanrednoj situaciji od info servisa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čitanje poruka info servisa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogućava aplikaciji čitanje poruka info servisa koje je primio vaš uređaj. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informaciju o vanrednoj situaciji od info servisa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čitanje sadržaja na koje ste pretplaćeni"</string>
@@ -519,10 +517,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Omogućava aplikaciji da sazna nivo kompleksnosti zaključavanja ekrana (visoki, srednji, niski ili bez zaključavanja), što naznačava mogući raspon trajanja i vrste zaključavanja ekrana. Aplikacija također može korisnicima predložiti da ažuriraju zaključavanje ekrana do određenog nivoa, ali korisnici slobodno mogu ignorirati prijedlog i napustiti stranicu. Važno je napomenuti da se zaključavanje ekrana ne pohranjuje kao obični tekst tako da aplikacija ne zna tačnu lozinku."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"koristi biometrijski hardver za otiske prstij"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Omogućava aplikaciji da za autentifikaciju koristi biometrijski hardver"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"upravljanje hardverom za otiske prstiju"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"upravljanje hardverom za otisak prsta"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Omogućava aplikaciji da koristi metode za dodavanje i brisanje šablona otisaka prstiju za upotrebu."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"korištenje hardvera za otiske prstiju"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Omogućava aplikaciji da za autentifikaciju koristi hardver za otiske prstiju"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"korištenje hardvera za otisak prsta"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Omogućava aplikaciji da za autentifikaciju koristi hardver za otisak prsta"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"izmjena muzičke kolekcije"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Omogućava aplikaciji da mijenja vašu muzičku kolekciju."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"izmjena kolekcije videozapisa"</string>
@@ -550,7 +548,7 @@
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vrijeme za prepoznavanje otiska prsta je isteklo. Pokušajte ponovo."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja s otiskom prsta je otkazana."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Korisnik je otkazao radnju s otiskom prsta."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Omogućava aplikaciji da čita i upisuje konfiguraciju načina rada Ne ometaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"pokrenuti korištenje odobrenja za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Dozvoljava vlasniku da pokrene korištenje odobrenja za aplikaciju. Ne bi trebalo biti potrebno za obične aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj prečice pristupačnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Omogućava aplikaciji da definira cilj prečice pristupačnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavljanje pravila za lozinke"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolira dužinu i znakove koji su dozvoljeni u lozinkama za zaključavanje ekrana i PIN-ovima."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Prati pokušaje otključavanja ekrana"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 8ef9a17..28b9a16 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -154,7 +154,7 @@
     <string name="fcComplete" msgid="3118848230966886575">"Codi de funció completat."</string>
     <string name="fcError" msgid="3327560126588500777">"Problema de connexió o codi de funció no vàlid."</string>
     <string name="httpErrorOk" msgid="1191919378083472204">"D\'acord"</string>
-    <string name="httpError" msgid="7956392511146698522">"S\'ha produït un error de xarxa."</string>
+    <string name="httpError" msgid="7956392511146698522">"S\'ha produït un error de la xarxa."</string>
     <string name="httpErrorLookup" msgid="4711687456111963163">"No s\'ha pogut trobar l\'URL."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"L\'esquema d\'autenticació de llocs no és compatible."</string>
     <string name="httpErrorAuth" msgid="1435065629438044534">"No s\'ha pogut autenticar."</string>
@@ -324,8 +324,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el nivell i la posició del zoom de la pantalla."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fer gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permet tocar, lliscar, pinçar i fer altres gestos."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos d\'empremtes digitals"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Captura gestos realitzats en el sensor d\'empremtes digitals del dispositiu."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos d\'empremtes dactilars"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Captura gestos realitzats en el sensor d\'empremtes dactilars del dispositiu."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra d\'estat"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"aparèixer a la barra d\'estat"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet que l\'aplicació rebi i processi missatges SMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recepció de missatges de text (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permet que l\'aplicació rebi i processi missatges MMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar els missatges de difusió mòbil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permet que l\'aplicació es vinculi al mòdul de difusió mòbil per poder reenviar els missatges de difusió mòbil a mesura que es reben. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rebi una difusió mòbil d\'emergència."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"llegir missatges de difusió mòbil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permet que l\'aplicació llegeixi missatges de difusió mòbil rebuts pel dispositiu. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rep una difusió mòbil d\'emergència."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"llegir els feeds als quals esteu subscrit"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Permet que l\'aplicació conegui el nivell de complexitat del bloqueig de pantalla (alt, mitjà, baix o cap), que indica la llargària i el tipus de bloqueig de pantalla possibles. L\'aplicació també pot suggerir que els usuaris actualitzin el bloqueig de pantalla a un nivell determinat, però els usuaris poden ignorar aquestes recomanacions. Tingues en compte que el bloqueig de pantalla no s\'emmagatzema com a text sense format, de manera que l\'aplicació no coneix la contrasenya exacta."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"utilitza maquinari biomètric"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Permet que l\'aplicació faci servir maquinari biomètric per a l\'autenticació"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"Gestionar el maquinari d\'empremtes digitals"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes digitals que es puguin fer servir."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes digitals"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet que l\'aplicació faci servir maquinari d\'empremtes digitals per a l\'autenticació"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"Gestionar el maquinari d\'empremtes dactilars"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes dactilars que es puguin fer servir."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes dactilars"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet que l\'aplicació faci servir maquinari d\'empremtes dactilars per a l\'autenticació"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"modificar la teva col·lecció de música"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Permet que l\'aplicació modifiqui la teva col·lecció de música."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"modificar la teva col·lecció de vídeos"</string>
@@ -534,30 +532,30 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"No s\'ha reconegut"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"S\'ha cancel·lat l\'autenticació"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"No s\'ha establert cap PIN, patró o contrasenya"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S\'ha detectat una empremta digital parcial. Torna-ho a provar."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor d\'empremtes digitals està brut. Neteja\'l i torna-ho a provar."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S\'ha detectat una empremta dactilar parcial. Torna-ho a provar."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No s\'ha pogut processar l\'empremta dactilar. Torna-ho a provar."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"El sensor d\'empremtes dactilars està brut. Neteja\'l i torna-ho a provar."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"El dit s\'ha mogut massa ràpid. Torna-ho a provar."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"El dit s\'ha mogut massa lentament. Torna-ho a provar."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"L\'empremta digital s\'ha autenticat"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"L\'empremta dactilar s\'ha autenticat"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Cara autenticada"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Cara autenticada; prem el botó per confirmar"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes digitals no està disponible."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta digital no es pot desar. Suprimeix-ne una."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"L\'usuari ha cancel·lat l\'operació d\'empremta digital."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"El maquinari per a empremtes dactilars no està disponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"L\'empremta dactilar no es pot desar. Suprimeix-ne una."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta dactilar. Torna-ho a provar."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta dactilar."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"L\'usuari ha cancel·lat l\'operació d\'empremta dactilar."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"S\'han produït massa intents. Torna-ho a provar més tard."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes digitals."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes dactilars."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Torna-ho a provar."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"No s\'ha registrat cap empremta digital."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Aquest dispositiu no té sensor d\'empremtes digitals."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Aquest dispositiu no té sensor d\'empremtes dactilars."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dit <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Icona d\'empremta digital"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Icona d\'empremta dactilar"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"gestiona el maquinari de desbloqueig facial"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"Permet que l\'aplicació afegeixi i suprimeixi plantilles de cares que es puguin fer servir."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"utilitza el maquinari de desbloqueig facial"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permet que l\'aplicació llegeixi la configuració No molestis i hi escrigui."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"comença a utilitzar el permís de visualització"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permet que un propietari comenci a utilitzar el permís amb una aplicació. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objectiu de la drecera d\'accessibilitat"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permet a una aplicació definir l\'objectiu de la drecera d\'accessibilitat."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Permet controlar la longitud i el nombre de caràcters permesos a les contrasenyes i als PIN del bloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Supervisar els intents de desbloqueig de la pantalla"</string>
@@ -1165,7 +1161,7 @@
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Esborra els paràmetres predeterminats a Configuració del sistema &gt; Aplicacions &gt; Baixades."</string>
     <string name="chooseActivity" msgid="7486876147751803333">"Selecciona una acció"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Tria una aplicació per al dispositiu USB"</string>
-    <string name="noApplications" msgid="2991814273936504689">"No hi ha cap aplicació que pugui dur a terme aquesta acció."</string>
+    <string name="noApplications" msgid="2991814273936504689">"No hi ha cap aplicació que pugui fer aquesta acció."</string>
     <string name="aerr_application" msgid="250320989337856518">"S\'ha aturat <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> s\'ha aturat"</string>
     <string name="aerr_application_repeated" msgid="3146328699537439573">"L\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> s\'atura contínuament"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 72e7a86..8ba6f34 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -234,7 +234,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Hlášení chyb"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Ukončit relaci"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Snímek obrazovky"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Zpráva o chybě"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Hlášení chyb"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Shromažďuje informace o aktuálním stavu zařízení. Tyto informace je následně možné poslat v e-mailové zprávě, chvíli však potrvá, než bude hlášení o chybě připraveno k odeslání. Buďte prosím trpěliví."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Interaktivní přehled"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Tato možnost se používá ve většině případů. Umožňuje sledovat průběh přehledu, zadat další podrobnosti o problému a pořizovat snímky obrazovky. Mohou být vynechány některé méně používané sekce, jejichž kontrola trvá dlouho."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Umožňuje aplikaci přijmout a zpracovat zprávy SMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"příjem textových zpráv (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Umožňuje aplikaci přijmout a zpracovat zprávy MMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Přesměrování zpráv informačních služeb"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Umožňuje aplikaci vytvořit vazbu s modulem informačních služeb za účelem přesměrovávání přijatých zpráv informačních služeb. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čtení zpráv informačních služeb"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Umožňuje aplikaci číst zprávy informačních služeb přijaté ve vašem zařízení. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čtení zdrojů přihlášených k odběru"</string>
@@ -523,7 +521,7 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"použití biometrického hardwaru"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Umožňuje aplikaci použít k ověření biometrický hardware"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"správa hardwaru na čtení otisků prstů"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikaci volat metody k přidání a smazání šablon otisků prstů, které budou použity."</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikaci volit metody k přidávání a mazání šablon otisků prstů, které budou použity."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"použití hardwaru na čtení otisků prstů"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikaci použít k ověření hardware na čtení otisků prstů"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"úprava hudební sbírky"</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Umožňuje aplikaci číst a zapisovat konfiguraci režimu Nerušit."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"zahájení zobrazení využití oprávnění"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Umožňuje přístup zahájit využití oprávnění jiné aplikace. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cíl zkratky přístupnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Umožňuje aplikaci definovat cíl zkratky přístupnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ovládání délky a znaků povolených v heslech a kódech PIN zámku obrazovky."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Sledovat pokusy o odemknutí obrazovky"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 88900a0..0d40688 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -75,7 +75,7 @@
     <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Standarder for opkalds-id til begrænset. Næste opkald: Ikke begrænset"</string>
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Standarder for opkalds-id til ikke begrænset. Næste opkald: Begrænset"</string>
     <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Standarder for opkalds-id til ikke begrænset. Næste opkald: Ikke begrænset"</string>
-    <string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjenesten leveres ikke!"</string>
+    <string name="serviceNotProvisioned" msgid="8614830180508686666">"Tjenesten provisioneres ikke."</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"Du kan ikke ændre indstillingen for opkalds-id\'et."</string>
     <string name="RestrictedOnDataTitle" msgid="5221736429761078014">"Ingen mobildatatjeneste"</string>
     <string name="RestrictedOnEmergencyTitle" msgid="6855466023161191166">"Det er ikke muligt at foretage nødopkald"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillader, at appen kan modtage og behandle sms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"modtage tekstbeskeder (mms)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Videresend Cell Broadcast-meddelelser"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tillader, at appen bindes til Cell Broadcast-modulet, så Cell Broadcast-meddelelser kan videresendes, når de modtages. I nogle områder sendes der Cell Broadcast-underretninger for at advare dig om nødsituationer. Ondsindede apps kan forstyrre effektiviteten eller driften af din enhed, når den modtager en Cell Broadcast-meddelelse om en nødsituation."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"læse Cell Broadcast-meddelelser"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillader, at appen læser Cell Broadcast-underretninger, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-underretninger for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af ​din ​enhed, når der modtages en Cell Broadcast-meddelelse om en nødsituation."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"læse feeds, jeg abonnerer på"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Giver appen tilladelse til at kende skærmlåsens kompleksitet (høj, medium, lav eller ingen), hvilket kan afsløre oplysninger om skærmlåsens længde og type. Appen kan også foreslå brugerne at opdatere deres skærmlås til et bestemt niveau, men brugerne kan frit ignorere det og gå videre. Bemærk! Skærmlåsen gemmes ikke som almindelig tekst, så appen kender ikke den nøjagtige adgangskode."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"brug biometrisk hardware"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Tillader, at appen kan bruge biometrisk hardware til godkendelse"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"administrer fingeraftrykhardware"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"administrer hardware til fingeraftryk"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillader, at appen kan køre metoder til at tilføje og slette fingeraftryksskabeloner"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruge fingeraftrykhardware"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillader, at appen kan bruge fingeraftrykhardware til godkendelse"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruge hardware til fingeraftryk"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillader, at appen kan bruge hardware til fingeraftryk til godkendelse"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"ændre din musiksamling"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Tillader, at appen kan ændre din musiksamling."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"ændre din videosamling"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Der er ikke angivet pinkode, mønster eller adgangskode"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Der blev registreret et delvist fingeraftryk. Prøv igen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingeraftrykket kunne ikke behandles. Prøv igen."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Sensoren til registrering af fingeraftryk er beskidt. Tør den af, og prøv igen."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingeraftrykslæseren er beskidt. Tør den af, og prøv igen."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Du bevægede fingeren for hurtigt. Prøv igen."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du bevægede fingeren for langsomt. Prøv igen."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Giver appen tilladelse til at læse og redigere konfigurationen af Forstyr ikke."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start brugen at tilladelsesvisning"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Tillader, at brugeren kan bruge en tilladelse for en app. Dette bør aldrig være nødvendigt for almindelige apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"mål for hjælpefunktionsgenvej"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tillader, at en app definerer målet for en hjælpefunktionsgenvej."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angiv regler for adgangskoder"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Tjek længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -1977,7 +1973,7 @@
     <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"Svar"</string>
     <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
     <string name="mmcc_authentication_reject" msgid="5767701075994754356">"SIM-kort er ikke tilladt for tale"</string>
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM-kort er ikke aktiveret for tale"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM-kort er ikke provisioneret til tale"</string>
     <string name="mmcc_illegal_ms" msgid="807334478177362062">"SIM-kort er ikke tilladt for tale"</string>
     <string name="mmcc_illegal_me" msgid="1950705155760872972">"Telefon er ikke tilladt for tale"</string>
     <string name="mmcc_authentication_reject_msim_template" msgid="1217031195834766479">"SIM-kortet <xliff:g id="SIMNUMBER">%d</xliff:g> er ikke tilladt"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6bf5404..f051345 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ermöglicht der App, SMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"MMS empfangen"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ermöglicht der App, MMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cell-Broadcast-Nachrichten weiterleiten"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ermöglicht der App, sich mit dem Cell-Broadcast-Modul zu verbinden, um empfangene Cell-Broadcast-Nachrichten weiterzuleiten. Cell-Broadcast-Benachrichtigungen können in einigen Ländern oder Regionen gesendet werden, um dich bei Notfallsituationen zu warnen. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell-Broadcast-Notfallbenachrichtigung eingeht."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Cell Broadcast-Nachrichten lesen"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ermöglicht der App, von deinem Gerät empfangene Cell Broadcast-Nachrichten zu lesen. Cell Broadcast-Benachrichtigungen werden an einigen Standorten gesendet, um dich über Notfallsituationen zu informieren. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell Broadcast-Notfallbenachrichtigung eingeht."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"Abonnierte Feeds lesen"</string>
@@ -546,7 +544,7 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Gesicht authentifiziert, bitte bestätigen"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Fingerabdruckhardware nicht verfügbar"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Fingerabdruck kann nicht gespeichert werden. Entferne einen vorhandenen Fingerabdruck."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Bitte versuche es noch einmal."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung bei Fingerabdruck. Bitte versuche es noch einmal."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerabdruckvorgang abgebrochen"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Vorgang der Fingerabdruckauthentifizierung vom Nutzer abgebrochen."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zu viele Versuche, bitte später noch einmal versuchen"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ermöglicht der App Lese- und Schreibzugriff auf die \"Bitte nicht stören\"-Konfiguration"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Mit der Verwendung der Anzeigeberechtigung beginnen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ermöglicht dem Inhaber, die Berechtigungsnutzung für eine App zu beginnen. Sollte für normale Apps nie benötigt werden."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Ziel der Verknüpfung für Bedienungshilfen"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ermöglicht einer App, das Ziel der Verknüpfung für Bedienungshilfen zu definieren."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1596,7 +1592,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Browser starten?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Anruf annehmen?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Immer"</string>
-    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Auf \"Immer geöffnet\" festlegen"</string>
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Auf \"Immer öffnen\" festlegen"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Nur diesmal"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Einstellungen"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"Das Arbeitsprofil wird von %1$s nicht unterstützt."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 3570fc1..a360de0 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Εκτέλεση κινήσεων"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Επιτρέπει το πάτημα, την ολίσθηση, το πλησίασμα και άλλες κινήσεις."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Κινήσεις δακτυλικών αποτυπωμάτων"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικών αποτυπωμάτων της συσκευής."</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικού αποτυπώματος της συσκευής."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ορίζεται ως γραμμή κατάστασης"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων SMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"λαμβάνει μηνύματα κειμένου (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων MMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Προώθηση μηνυμάτων εκπομπής κινητής τηλεφωνίας"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Επιτρέπει στην εφαρμογή να συνδέεται στη λειτουργική μονάδα εκπομπής κινητής τηλεφωνίας, προκειμένου να προωθεί τα μηνύματα εκπομπής κινητής τηλεφωνίας κατά τη λήψη τους. Οι ειδοποιήσεις εκπομπής κινητής τηλεφωνίας προβάλλονται σε ορισμένες τοποθεσίες, για να σας προειδοποιήσουν σχετικά με καταστάσεις έκτακτης ανάγκης. Οι κακόβουλες εφαρμογές μπορεί να επηρεάσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μιας εκπομπής κινητής τηλεφωνίας έκτακτης ανάγκης."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"διαβάζει μηνύματα που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Επιτρέπει στην εφαρμογή να μάθει το επίπεδο πολυπλοκότητας του κλειδώματος οθόνης (υψηλό, μέσο, χαμηλό ή κανένα), το οποίο υποδεικνύει το πιθανό εύρος του μήκους και του τύπου κλειδώματος οθόνης. Η εφαρμογή μπορεί επίσης να προτείνει στους χρήστες να ενημερώσουν το κλείδωμα οθόνης σε ένα συγκεκριμένο επίπεδο, όμως οι χρήστες μπορούν να την αγνοήσουν και να συνεχίσουν. Λάβετε υπόψη ότι το κλείδωμα οθόνης δεν αποθηκεύεται σε απλό κείμενο. Συνεπώς, η εφαρμογή δεν γνωρίζει τον κωδικό."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"χρήση βιομετρικού εξοπλισμού"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί βιομετρικό εξοπλισμό για έλεγχο ταυτότητας"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"διαχειρίζεται τον εξοπλισμό δακτυλικού αποτυπώματος"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων μοναδικού χαρακτηριστικού για χρήση."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρησιμοποιεί τον εξοπλισμό δακτυλικού αποτυπώματος"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό μοναδικού χαρακτηριστικού για έλεγχο ταυτότητας"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"διαχείριση εξοπλισμού δακτυλικού αποτυπώματος"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων δακτυλικών αποτυπωμάτων για χρήση."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρήση εξοπλισμού δακτυλικού αποτυπώματος"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό δακτυλικού αποτυπώματος για έλεγχο ταυτότητας"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"τροποποίηση της μουσικής συλλογής σας"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη μουσική συλλογή σας."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"τροποποίηση της συλλογής βίντεό σας"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Δεν αναγνωρίστηκε"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Ο έλεγχος ταυτότητας ακυρώθηκε"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Δεν έχει οριστεί PIN, μοτίβο ή κωδικός πρόσβασης"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μερικό μοναδικό χαρακτηριστικό. Δοκιμάστε ξανά."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Ο αισθητήρας μοναδικού χαρακτηριστικού δεν είναι καθαρός. Καθαρίστε τον και δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μόνο μέρος του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Ο αισθητήρας δακτυλικού αποτυπώματος δεν είναι καθαρός. Καθαρίστε τον και δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Πολύ γρήγορη κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Πολύ αργή κίνηση δαχτύλου. Δοκιμάστε ξανά."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -544,16 +542,16 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Η ταυτότητα του δακτυλικού αποτυπώματος ελέγχθηκε"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Έγινε έλεγχος ταυτότητας προσώπου"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Έγινε έλεγχος ταυτότητας προσώπου, πατήστε \"Επιβεβαίωση\""</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Ο εξοπλισμός μοναδικού χαρακτηριστικού δεν είναι διαθέσιμος."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Δεν είναι δυνατή η αποθήκευση μοναδικού χαρακτηριστικού. Καταργήστε το υπάρχον μοναδικό χαρακτηριστικό."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Η λειτουργία μοναδικού χαρακτηριστικού ακυρώθηκε."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Ο εξοπλισμός δακτυλικού αποτυπώματος δεν είναι διαθέσιμος."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Δεν είναι δυνατή η αποθήκευση του δακτυλικού αποτυπώματος. Καταργήστε το υπάρχον δακτυλικό αποτύπωμα."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε από τον χρήστη."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Πάρα πολλές προσπάθειες. Ο αισθητήρας δακτυλικών αποτυπωμάτων απενεργοποιήθηκε."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Δοκιμάστε ξανά."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Δεν έχουν καταχωριστεί δακτυλικά αποτυπώματα."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικών αποτυπωμάτων."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικού αποτυπώματος."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Δάχτυλο <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Επιτρέπει στην εφαρμογή την εγγραφή και τη σύνταξη διαμόρφωσης για τη λειτουργία \"Μην ενοχλείτε\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"έναρξη χρήσης άδειας προβολής"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Επιτρέπει στον κάτοχο να ξεκινήσει τη χρήση της άδειας για μια εφαρμογή. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"στόχος συντόμευσης προσβασιμότητας"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Επιτρέπει σε μια εφαρμογή να καθορίσει τον στόχο της συντόμευσης προσβασιμότητας."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ελέγξτε την έκταση και τους επιτρεπόμενους χαρακτήρες σε κωδικούς πρόσβασης κλειδώματος οθόνης και PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index e1d9875..1e0e93a 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"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>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. 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 mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 56b54d9..4deaf2e 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"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>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. 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 mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index e1d9875..1e0e93a 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"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>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. 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 mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e1d9875..1e0e93a 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Allows the app to receive and process SMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receive text messages (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Forward cell broadcast messages"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"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>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Allows the app to read mobile broadcast messages received by your device. 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 mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"read subscribed feeds"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Allows the app to read and write Do Not Disturb configuration."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start view permission usage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Allows the holder to start the permission usage for an app. Should never be needed for normal apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"accessibility shortcut target"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Allows an app to define the accessibility shortcut target."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Control the length and the characters allowed in screen lock passwords and PINs."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitor screen unlock attempts"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index c4d3157..5fe1bb1 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎Allows the app to receive and process SMS messages. This means the app could monitor or delete messages sent to your device without showing them to you.‎‏‎‎‏‎"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎receive text messages (MMS)‎‏‎‎‏‎"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎Allows the app to receive and process MMS messages. This means the app could monitor or delete messages sent to your device without showing them to you.‎‏‎‎‏‎"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‎Forward cell broadcast messages‎‏‎‎‏‎"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‎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>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎read cell broadcast messages‎‏‎‎‏‎"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‏‏‎Allows the app to read cell broadcast messages received by your device. 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>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎read subscribed feeds‎‏‎‎‏‎"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎Allows the app to read and write Do Not Disturb configuration.‎‏‎‎‏‎"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‎start view permission usage‎‏‎‎‏‎"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎Allows the holder to start the permission usage for an app. Should never be needed for normal apps.‎‏‎‎‏‎"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎accessibility shortcut target‎‏‎‎‏‎"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎Allows an app to define the accessibility shortcut target.‎‏‎‎‏‎"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‏‎Set password rules‎‏‎‎‏‎"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎Control the length and the characters allowed in screen lock passwords and PINs.‎‏‎‎‏‎"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎Monitor screen unlock attempts‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 30f8ba7..feb4aee 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que la aplicación reciba y procese mensajes SMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensajes de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar mensajes de emisión móvil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que la app se vincule al módulo de emisión móvil para reenviar los mensajes de este tipo a medida que se reciben. En algunas ubicaciones, se envían alertas de emisión móvil para advertirte en situaciones de emergencia. Es posible que las apps maliciosas interfieran con el rendimiento o el funcionamiento de tu dispositivo cuando recibes una emisión móvil de emergencia."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Leer mensajes de difusión móvil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite a la aplicación leer los mensajes de difusión móvil que recibe tu dispositivo. En algunas ubicaciones, las alertas de difusión móvil se envían para informar situaciones de emergencia. Las aplicaciones maliciosas pueden afectar el rendimiento o funcionamiento de tu dispositivo cuando se recibe un un mensaje de difusión móvil de emergencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"leer canales suscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite que la aplicación lea y modifique la configuración de la función No interrumpir."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso de permiso de vista"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que el propietario inicie el uso de permisos para una app. No debería requerirse para apps normales."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"orientación del acceso directo de accesibilidad"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que una app defina la orientación del acceso directo de accesibilidad."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlar la longitud y los caracteres permitidos en las contraseñas y los PIN para el bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Supervisa los intentos para desbloquear la pantalla"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 15e662c..75510b3 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -230,7 +230,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Informe de error"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Finalizar sesión"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Informe de errores"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Informar de un error"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Se recopilará información sobre el estado actual de tu dispositivo y se enviará por correo electrónico. Pasarán unos minutos desde que empiece a generarse el informe de errores hasta que se envíe."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Informe interactivo"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Usa esta opción en la mayoría de los casos. Te permite realizar un seguimiento del progreso del informe, introducir más información sobre el problema y hacer capturas de pantalla. Es posible que se omitan algunas secciones menos utilizadas y que requieran más tiempo."</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensajes de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar mensajes de difusión móvil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que la aplicación se vincule con el módulo de difusión móvil para reenviar los mensajes de ese tipo en cuanto se reciben. En ciertas ubicaciones se envían alertas de difusión móvil para avisar de situaciones de emergencia. Cuando se recibe una alerta de difusión móvil de emergencia, ciertas aplicaciones malintencionadas podrían interferir en el rendimiento o en el funcionamiento del dispositivo."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"leer mensajes de difusión móvil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que la aplicación lea mensajes de difusión móvil que haya recibido el dispositivo. Las alertas de difusión móvil se envían en algunas ubicaciones para avisar de situaciones de emergencia. Es posible que las aplicaciones malintencionadas interfieran en el rendimiento o en el funcionamiento del dispositivo si se recibe una alerta de difusión móvil de emergencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"leer feeds a los que está suscrito el usuario"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite que la aplicación lea y modifique la configuración de No molestar."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso de permiso de visualización"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que el titular inicie el uso de permisos de una aplicación. Las aplicaciones normales no deberían necesitar nunca este permiso."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objetivo de atajo de accesibilidad"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que una aplicación defina el objetivo de un atajo de accesibilidad."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla la longitud y los caracteres permitidos en los PIN y en las contraseñas de bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Supervisar los intentos de desbloqueo de pantalla"</string>
@@ -1195,7 +1191,7 @@
     <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar siempre"</string>
     <string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g> se diseñó para una versión incompatible de Android OS y puede que funcione de forma inesperada. Es posible que haya una versión actualizada de la aplicación."</string>
     <string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"Mostrar siempre"</string>
-    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Comprobar actualizaciones"</string>
+    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Buscar actualizaciones"</string>
     <string name="smv_application" msgid="3307209192155442829">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha infringido su política StrictMode autoaplicable."</string>
     <string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha infringido su política StrictMode autoaplicable."</string>
     <string name="android_upgrading_title" product="default" msgid="7513829952443484438">"El teléfono se está actualizando…"</string>
@@ -1914,7 +1910,7 @@
     <string name="work_mode_off_message" msgid="5130856710614337649">"Tus aplicaciones, notificaciones, datos y otras funciones del perfil de trabajo se activarán"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
     <string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Esta aplicación se ha diseñado para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o ponte en contacto con el desarrollador."</string>
-    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Comprobar actualizaciones"</string>
+    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Buscar actualizaciones"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre la aplicación de SMS para ver el mensaje"</string>
     <string name="profile_encrypted_title" msgid="4260432497586829134">"Algunas funciones limitadas"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 093f7d7..0e7befd 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Võimaldab rakendusel vastu võtta ja töödelda SMS-sõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"võtke vastu tekstisõnumeid (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Võimaldab rakendusel vastu võtta ja töödelda multimeediumsõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Kärjeteadete edasisaatmine"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Võimaldab rakendusel luua ühenduse kärjeteadete mooduliga, et saabunud kärjeteateid edasi saata. Kärjeteateid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad seadme toimivust või tööd eriolukorra kärjeteate vastuvõtmisel segada."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"mobiilsidesõnumite lugemine"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Võimaldab rakendusel lugeda seadme vastu võetud mobiilsidesõnumeid. Mobiilsidemärguandeid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad segada seadme toimivust või tööd eriolukorra sõnumi vastuvõtmisel."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"loe tellitud kanaleid"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Võimaldab rakendusel lugeda ja kirjutada funktsiooni Mitte segada seadistusi."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"vaatamisloa kasutamise alustamine"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Võimaldab omanikul rakenduse puhul alustada loa kasutamist. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"juurdepääsetavuse otsetee sihtmärk"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Lubab rakendusel määrata juurdepääsetavuse otsetee sihtmärgi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Juhitakse ekraaniluku paroolide ja PIN-koodide pikkusi ning lubatud tähemärkide seadeid."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekraani avamiskatsete jälgimine"</string>
@@ -1145,7 +1141,7 @@
     <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Linkide avamine rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
     <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Ava teenuse <xliff:g id="HOST">%1$s</xliff:g> lingid rakendusega <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Juudep. andmine"</string>
-    <string name="whichEditApplication" msgid="144727838241402655">"Muutmine:"</string>
+    <string name="whichEditApplication" msgid="144727838241402655">"Redigeeri rakendusega:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Muutmine rakendusega %1$s"</string>
     <string name="whichEditApplicationLabel" msgid="7183524181625290300">"Muuda"</string>
     <string name="whichSendApplication" msgid="5803792421724377602">"Jagamine"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 53b1a38..22391dc 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"jaso testu-mezuak (MMSak)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Desbideratu sare mugikor bidezko igorpen-mezuak"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, aplikazio maltzurrek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"irakurri sare mugikor bidezko igorpen-mezuak"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Gailuak jasotako sare mugikor bidezko igorpenen mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Aplikazio gaiztoek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"irakurri harpidetutako jarioak"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Pantailaren blokeoaren konplexutasun-maila (handia, ertaina, txikia edo bat ere ez) jakiteko aukera ematen dio aplikazioari. Informazio horrekin, pantailaren blokeoaren luzera-barruti edo mota posiblea ondoriozta liteke. Halaber, pantailaren blokeoa maila jakin batera igotzeko iradoki diezaieke aplikazioak erabiltzaileei, baina horri ez ikusi egin eta aplikazioa erabiltzen jarraitzeko aukera dute erabiltzaileek. Kontuan izan pantailaren blokeoa ez dela gordetzen testu arrunt gisa; beraz, aplikazioak ez du jakingo pasahitz zehatza zein den."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"Erabili hardware biometrikoa"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Autentifikatzeko hardware biometrikoa erabiltzeko baimena ematen die aplikazioei."</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"kudeatu erreferentzia-gako digitalen hardwarea"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"kudeatu hatz-marken hardwarea"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Erreferentzia-gako digitalen txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"erabili erreferentzia-gako digitalen hardwarea"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko erreferentzia-gako digitalen hardwarea erabiltzeko baimena ematen die aplikazioei."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"erabili hatz-marken hardwarea"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko hatz-marken hardwarea erabiltzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"musika-bilduma aldatu"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Musika-bilduma aldatzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"bideo-bilduma aldatu"</string>
@@ -544,7 +542,7 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Autentifikatu da hatz-marka"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Autentifikatu da aurpegia"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Autentifikatu da aurpegia; sakatu Berretsi"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hatz-markaren hardwarea ez dago erabilgarri."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hatz-marken hardwarea ez dago erabilgarri."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Ezin da gorde hatz-marka digitala. Kendu lehendik gordeta duzunetako bat."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-markak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hatz-markaren eragiketa bertan behera utzi da."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"\"Ez molestatu\" konfigurazioa irakurtzeko eta bertan idazteko baimena ematen die aplikazioei."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"hasi ikusteko baimena erabiltzen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Aplikazioaren baimena erabiltzen hasteko baimena ematen die titularrei. Aplikazio normalek ez lukete beharko."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"erabilerraztasun-lasterbidearen helburua"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Erabilerraztasun-lasterbidearen helburua zehazteko baimena ematen dio aplikazioari."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ezarri pasahitzen arauak"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolatu pantaila blokeoaren pasahitzen eta PINen luzera eta onartutako karaktereak."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Gainbegiratu pantaila desblokeatzeko saiakerak"</string>
@@ -1556,7 +1552,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Aukera gehiago"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Barneko biltegiratze partekatua"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Barneko memoria partekatua"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD txartela"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD txartela"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB bidezko unitatea"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2b849d5..33421c0 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"به برنامه اجازه می‌دهد پیامک‌ها را دریافت و پردازش کند. این یعنی برنامه می‌تواند پیام‌های ارسالی به دستگاه شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"دریافت پیام‌های نوشتاری (فراپیام)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"به برنامه اجازه می‌دهد پیام‌های فراپیام را دریافت و پردازش کند. این یعنی برنامه می‌تواند پیام‌های ارسالی به دستگاه شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"بازارسال پیام‌های پخش سلولی"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"به برنامه امکان می‌دهد به مدول پخش سلولی متصل شود تا پیام‌های پخش سلولی را به محض دریافت بازارسال کند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی ارسال می‌شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‌شود، ممکن است برنامه‌های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"خواندن پیام‌های پخش سلولی"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"‏به برنامه اجازه می‎دهد پیام‌های پخش سلولی دستگاه شما را بخواند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی تحویل داده می‎شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‎شود، ممکن است برنامه‎های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"خواندن فیدهای مشترک"</string>
@@ -553,7 +551,7 @@
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"تلاش‌های بسیاری زیادی انجام شده است. حسگر اثر انگشت غیرفعال شد."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوباره امتحان کنید."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"اثر انگشتی ثبت نشده است."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"این دستگاه حسگر اثرانگشت ندارد."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"این دستگاه حسگر اثر انگشت ندارد."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"به برنامه امکان می‌دهد پیکربندی «مزاحم نشوید» را بخواند و بنویسد."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"شروع مشاهده استفاده از مجوز"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"به دارنده اجازه شروع استفاده از مجوز را برای برنامه می‌دهد. هرگز برای برنامه‌های معمول نیاز نیست."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"مقصد میان‌بر دسترس‌پذیری"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"به برنامه اجازه می‌دهد مقصد میانبر دسترس‌پذیری را تعریف کند."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین گذرواژه"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"کنترل طول و نوع نویسه‌هایی که در گذرواژه و پین قفل صفحه مجاز است."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"پایش تلاش‌های باز کردن قفل صفحه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c18e5bf..124a160 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -332,7 +332,7 @@
     <string name="permdesc_statusBarService" msgid="716113660795976060">"Antaa sovelluksen sijaita tilapalkissa."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"laajentaa/tiivistää tilarivin"</string>
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Antaa sovelluksen laajentaa tai tiivistää tilarivin."</string>
-    <string name="permlab_install_shortcut" msgid="4279070216371564234">"asenna pikakuvakkeita"</string>
+    <string name="permlab_install_shortcut" msgid="4279070216371564234">"asentaa pikakuvakkeita"</string>
     <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Antaa sovelluksen lisätä aloitusruudun pikakuvakkeita ilman käyttäjän toimia."</string>
     <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"poista pikakuvakkeita"</string>
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Antaa sovelluksen poistaa aloitusruudun pikakuvakkeita ilman käyttäjän toimia."</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Antaa sovelluksen vastaanottaa ja käsitellä tekstiviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"vastaanota tekstiviestejä (multimedia)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Antaa sovelluksen vastaanottaa ja käsitellä multimediaviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Lähetä solulähetysviestit edelleen"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Sallii sovelluksen sitoutua solulähetysmoduuliin lähettääkseen solulähetysviestejä edelleen sitä mukaa kun ne saapuvat. Solulähetysilmoitusten avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätilanteeseen liittyvän solulähetysviestin."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lue tiedotteita"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Antaa sovelluksen lukea laitteesi vastaanottamia tiedotteita. Tiedotteiden avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätiedotteen."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lukea tilattuja syötteitä"</string>
@@ -386,7 +384,7 @@
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Antaa sovelluksen noutaa sen koodin, tietojen ja välimuistin koot."</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"muokkaa järjestelmän asetuksia"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"Antaa sovelluksen muokata järjestelmän asetustietoja. Haitalliset sovellukset voivat vahingoittaa järjestelmän määritystä."</string>
-    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"suorita laitteen käynnistyessä"</string>
+    <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"suorittaa laitteen käynnistyessä"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Antaa sovelluksen käynnistyä heti, kun laite on käynnistynyt. Tämä voi pidentää tablet-laitteen käynnistysaikaa ja hidastaa sen yleistä käyttöä sovelluksen ollessa aina käynnissä."</string>
     <string name="permdesc_receiveBootCompleted" product="tv" msgid="6725487837446317527">"Antaa sovelluksen käynnistyä heti, kun laite on käynnistynyt. Tämä voi pidentää Android TV ‑laitteen käynnistysaikaa ja hidastaa sen yleistä käyttöä sovelluksen ollessa aina käynnissä."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Antaa sovelluksen käynnistyä heti, kun laite on käynnistynyt. Tämä voi pidentää puhelimen käynnistysaikaa ja hidastaa puhelimen yleistä käyttöä sovelluksen ollessa aina käynnissä."</string>
@@ -440,7 +438,7 @@
     <string name="permdesc_camera" msgid="5392231870049240670">"Tämä sovellus voi ottaa kameralla kuvia ja videoita koska tahansa."</string>
     <string name="permlab_systemCamera" msgid="4074081285026193898">"Salli sovellukselle tai palvelulle pääsy järjestelmän kameroihin, jotta se voi ottaa kuvia ja nauhoittaa videoita"</string>
     <string name="permdesc_systemCamera" msgid="6488131672529669229">"Tämä käyttöoikeuden saanut | järjestelmäsovellus voi ottaa järjestelmän kameralla kuvia ja videoita koska tahansa. Sovelluksella on oltava myös android.permission.CAMERA-käyttöoikeus"</string>
-    <string name="permlab_vibrate" msgid="7696427026057705834">"hallitse värinää"</string>
+    <string name="permlab_vibrate" msgid="7696427026057705834">"hallita värinää"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Antaa sovelluksen hallita värinää."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"soittaa puhelinnumeroihin suoraan"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Antaa sovelluksen soittaa puhelinnumeroihin kysymättä sinulta. Tämä voi aiheuttaa odottamattomia kuluja tai puheluita. Huomaa, että tämä ei anna sovellukselle lupaa soittaa hätänumeroihin. Haitalliset sovellukset voivat aiheuttaa sinulle kuluja soittamalla puheluita ilman lupaa."</string>
@@ -478,7 +476,7 @@
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Antaa sovelluksen tarkastella tablet-laitteeseen tallennettuja tilejä. Näihin voivat kuulua myös asentamiesi sovelluksien luomat tilit."</string>
     <string name="permdesc_getAccounts" product="tv" msgid="1394648459318596337">"Antaa sovelluksen noutaa Android TV ‑laitteen tuntemien tilien listan. Tileihin voi kuulua myös asennettujen sovellusten luomia tilejä."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Antaa sovelluksen tarkastella puhelimeen tallennettuja tilejä. Näihin voivat kuulua myös asentamiesi sovelluksien luomat tilit."</string>
-    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"tarkastele verkkoyhteyksiä"</string>
+    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"tarkastella verkkoyhteyksiä"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Antaa sovelluksen tarkastella verkkoyhteyksiä koskevia tietoja, kuten mitä verkkoja on olemassa ja mihin on muodostettu yhteys."</string>
     <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"saada täydet verkon käyttöoikeudet"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Antaa sovelluksen luoda verkkovastakkeita ja käyttää muokattuja verkkoprotokollia. Tietoja voidaan lähettää verkkoon selaimen ja muiden sovellusten avulla, joten tätä lupaa ei tarvita tietojen lähettämiseksi."</string>
@@ -486,7 +484,7 @@
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Antaa sovelluksen muuttaa verkkoyhteyden tilaa."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"internetyhteyden jakamisen muuttaminen"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Antaa sovelluksen muuttaa internetyhteyden jakamisen tilaa."</string>
-    <string name="permlab_accessWifiState" msgid="5202012949247040011">"näytä Wi-Fi-yhteydet"</string>
+    <string name="permlab_accessWifiState" msgid="5202012949247040011">"nähdä Wi-Fi-yhteydet"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Antaa sovelluksen tarkastella Wi-Fi-verkkoja koskevia tietoja, kuten onko Wi-Fi käytössä ja mihin Wi-Fi-laitteisiin on muodostettu yhteys."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"muodosta ja katkaise Wi-Fi-yhteys"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Antaa sovelluksen yhdistää Wi-Fi-tukiasemiin tai katkaista yhteyden sekä tehdä muutoksia määritettyihin Wi-Fi-verkkoihin."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Sallii sovelluksen lukea ja muokata Älä häiritse -tilan asetuksia."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"aloita katseluoikeuksien käyttö"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Antaa luvanhaltijan käynnistää sovelluksen käyttöoikeuksien käytön. Ei tavallisten sovelluksien käyttöön."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"esteettömyystilan pikakuvakkeen kohde"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Sallii sovelluksen määrittää kohteen esteettömystilan pikakuvakkeelle."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Asentaa salasanasäännöt"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Hallinnoida ruudun lukituksen salasanoissa ja PIN-koodeissa sallittuja merkkejä ja niiden pituutta."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Tarkkailla näytön avaamisyrityksiä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 3bd5c23..ecfdcd2 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet à l\'application de recevoir et de traiter les messages texte. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recevoir des messages multimédias"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permet à l\'application de recevoir et de traiter les messages multimédias. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Transférer les messages de diffusion cellulaire"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permet à l\'application d\'établir un lien avec le module de diffusion cellulaire afin de transférer les messages de diffusion cellulaire à mesure de leur réception. Dans certaines régions, des alertes de diffusion cellulaire sont envoyées afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lire les messages de diffusion cellulaire"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permet à l\'application de lire les messages de diffusion cellulaire que votre appareil reçoit. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Des applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lors de la réception d\'un message de diffusion cellulaire."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lire les flux auxquels vous êtes abonné"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"démarrer l\'affichage de l\'usage des autorisations"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permet au détenteur de démarrer l\'usage des autorisations pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cible du raccourci d\'accessibilité"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permet à une application de définir la cible du raccourci d\'accessibilité."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les NIP de verrouillage de l\'écran."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"Numéro de série :"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Empreintes :"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"Empreinte digitale SHA-256 :"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Empreinte digitale SHA-1 :"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Empreinte SHA-1 :"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Tout afficher"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Sélectionnez une activité"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Partagez avec"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 8520c13..1a44b79 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permet à l\'application de recevoir et de traiter les SMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recevoir des messages texte (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permet à l\'application de recevoir et de traiter les MMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Transférer les messages reçus via un canal de diffusion cellulaire"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Autorise l\'application à établir une connexion avec le module de diffusion cellulaire afin de transférer les messages reçus via un canal de diffusion cellulaire. Des alertes de diffusion cellulaire sont générées dans certaines régions afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lire les messages reçus via un canal de diffusion cellulaire"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permet à l\'application de lire les messages que votre appareil reçoit via un canal de diffusion cellulaire. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Les applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lorsqu\'un message est reçu via un canal de diffusion cellulaire."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lire les flux auxquels vous êtes abonné"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Non reconnu"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Authentification annulée"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Aucun code, schéma ni mot de passe n\'est défini"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte numérique partiellement détectée. Veuillez réessayer."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte digitale partiellement détectée. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de reconnaître l\'empreinte digitale. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Le lecteur d\'empreinte digitale est sale. Veuillez le nettoyer, puis réessayer."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Vous avez déplacé votre doigt trop rapidement. Veuillez réessayer."</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Empreinte digitale authentifiée"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Visage authentifié"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Visage authentifié, veuillez appuyer sur \"Confirmer\""</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte numérique indisponible."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossible d\'enregistrer l\'empreinte numérique. Veuillez supprimer une empreinte."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Matériel d\'empreinte digitale indisponible."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Impossible d\'enregistrer l\'empreinte digitale. Veuillez en supprimer une autre."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte digitale expiré. Veuillez réessayer."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte digitale annulée."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Opération d\'authentification par empreinte digitale annulée par l\'utilisateur."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Trop de tentatives. Lecteur d\'empreinte digitale désactivé."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"activer l\'utilisation de l\'autorisation d\'affichage"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permet à l\'application autorisée d\'activer l\'utilisation de l\'autorisation pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cible du raccourci d\'accessibilité"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Autorise une application à définir la cible du raccourci d\'accessibilité."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les codes d\'accès de verrouillage de l\'écran"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Gérer les tentatives de déverrouillage de l\'écran"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 78c7d03..933fbab 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite á aplicación recibir e procesar mensaxes SMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensaxes de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite á aplicación recibir e procesar mensaxes MMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Reenviar mensaxes de difusión móbil"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que a aplicación se vincule ao módulo de difusión móbil para reenviar as mensaxes deste tipo segundo se reciban. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. As aplicacións maliciosas poden interferir no rendemento ou funcionamento do teu dispositivo cando se reciba unha difusión móbil de emerxencia."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensaxes de difusión móbil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite á aplicación ler mensaxes de difusión móbil recibidas polo teu dispositivo. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. É posible que aplicacións maliciosas afecten ao rendemento ou funcionamento do teu dispositivo cando se recibe unha difusión móbil de emerxencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds subscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite á aplicación ler e escribir a configuración do modo Non molestar."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso de permiso de vista"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite ao propietario iniciar o uso de permisos dunha aplicación. As aplicacións normais non deberían precisalo nunca."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"obxectivo do atallo de accesibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que unha aplicación defina o obxectivo do atallo de accesibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer as normas de contrasinal"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla a lonxitude e os caracteres permitidos nos contrasinais e nos PIN de bloqueo da pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Controlar os intentos de desbloqueo da pantalla"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 340245a..05e5a4e 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ઍપ્લિકેશનને SMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ટેક્સ્ટ સંદેશા (MMS) પ્રાપ્ત કરો"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ઍપ્લિકેશનને MMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"સેલ બ્રોડકાસ્ટ સંદેશા ફૉરવર્ડ કરો"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"સેલ બ્રોડકાસ્ટ સંદેશા પ્રાપ્ત થાય કે તરત ફૉરવર્ડ કરવા માટે સેલ બ્રોડકાસ્ટ મૉડ્યૂલ સાથે પ્રતિબદ્ધ થવા બાબતે ઍપને મંજૂરી આપે છે. તમને કટોકટીની પરિસ્થિતિની ચેતવણી આપવા માટે સેલ બ્રોડકાસ્ટ અલર્ટ અમુક સ્થાનોમાં ડિલિવર કરવામાં આવે છે. કટોકટી અંગેનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય, ત્યારે દુર્ભાવનાપૂર્ણ ઍપ તમારા ડિવાઇસના કાર્યપ્રદર્શન અથવા ઑપરેશનમાં વિક્ષેપ પાડે તેમ બની શકે છે."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"સેલ બ્રોડકાસ્ટ સંદેશા વાંચો"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"એપ્લિકેશનને તમારા ઉપકરણ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને કટોકટીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે કટોકટીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા ઉપકરણના પ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"સબ્સ્ક્રાઇબ કરેલ ફીડ્સ વાંચો"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"એપ્લિકેશનને ખલેલ પાડશો નહીં ગોઠવણી વાંચવા અને લખવાની મંજૂરી આપે છે."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"પરવાનગી વપરાશ જુઓને શરૂ કરો"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"કોઈ ઍપ માટે પરવાનગી વપરાશ શરૂ કરવાની ધારકને મંજૂરી આપે છે. સામાન્ય ઍપ માટે ક્યારેય જરૂર પડી ન શકે."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ઍક્સેસિબિલિટી શૉર્ટકટ ટાર્ગેટ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ઍપને ઍક્સેસિબિલિટી શૉર્ટકટ ટાર્ગેટ વ્યાખ્યાતિત કરવાની મંજૂરી આપે છે."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"પાસવર્ડ નિયમો સેટ કરો"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"સ્ક્રીન લૉક પાસવર્ડ અને પિનમાં મંજૂર લંબાઈ અને અક્ષરોને નિયંત્રિત કરો."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"સ્ક્રીનને અનલૉક કરવાના પ્રયત્નોનું નિયમન કરો"</string>
@@ -1938,7 +1934,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"સમાચાર અને સામાયિકો"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"નકશા અને નેવિગેશન"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ઉત્પાદકતા"</string>
-    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ઉપકરણ સ્ટૉરેજ"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ડિવાઇસ સ્ટૉરેજ"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"USB ડિબગિંગ"</string>
     <string name="time_picker_hour_label" msgid="2979075098868106450">"કલાક"</string>
     <string name="time_picker_minute_label" msgid="5168864173796598399">"મિનિટ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8f78f95..f16ad65 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -295,7 +295,7 @@
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को एसएमएस (मैसेज) भेजने और देखने की अनुमति देना चाहते हैं?"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"मेमोरी"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"अपने डिवाइस पर मौजूद फ़ोटो, मीडिया और फ़ाइलें ऐक्सेस करने की"</string>
-    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस पर मौजूद फ़ोटो, ऑडियो-वीडियो और फ़ाइलें ऐक्सेस करने की अनुमति दें?"</string>
+    <string name="permgrouprequest_storage" msgid="7885942926944299560">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस पर मौजूद फ़ोटो, ऑडियो-वीडियो, और फ़ाइलें ऐक्सेस करने की अनुमति दें?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"माइक्रोफ़ोन"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ऑडियो रिकॉर्ड करें"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को ऑडियो रिकॉर्ड करने की अनुमति देना चाहते हैं?"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"एप्लिकेशन को मैसेज (एसएमएस) पाने और प्रोसेस करने देता है. इसका मतलब है कि एप्लिकेशन आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्‍हें हटा सकता है."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"मैसेज (एमएमएस) पाएं"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ऐप को मल्टीमीडिया मैसेज (एमएमएस) को पाने और उन पर कार्रवाई करने देता है. इसका मतलब है कि ऐप आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्‍हें हटा सकता है."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"सेल ब्रॉडकास्ट (CBC) मैसेज दूसरे नंबर पर भेजें"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"सेल ब्रॉडकास्ट (CBC) मैसेज आते ही उसे दूसरे नंबर पर भेजने के लिए, ऐप्लिकेशन को सेल ब्रॉडकास्ट (CBC) मॉड्यूल पर बाइंड करने की अनुमति देता है. कुछ जगहों में सेल ब्रॉडकास्ट (CBC) अलर्ट आपातकालीन स्थितियों के बारे में चेतावनी देने के लिए भेजा जाता है. नुकसान पहुंचाने वाले ऐप्लिकेशन, आपातकाल में सेल ब्रॉडकास्ट (CBC) मैसेज मिलने पर आपके डिवाइस के काम करते समय या इसके परफ़ॉर्मेंस में रुकावट पैदा कर सकते हैं."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ें"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ऐप को, वो सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ने देता है जो आपके डिवाइस को मिले हैं. सेल ब्रॉडकास्ट (CBC) अलर्ट कुछ स्थानों (लोकेशन) पर आपको आपातकालीन स्‍थितियों की चेतावनी देने के लिए दिए जाते हैं. आपातकालीन सेल ब्रॉडकास्ट (CBC) मिलने पर, धोखा देने वाले ऐप आपके डिवाइस के परफ़ॉर्मेंस या कार्यवाही में दखल दे सकते हैं."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता वाली फ़ीड पढ़ें"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"यह मंज़ूरी मिलने के बाद ऐप्लिकेशन जान पाता है कि स्क्रीन लॉक कितना मुश्किल (बहुत ज़्यादा, मध्यम, कम या बिल्कुल नहीं) है. इस स्तर से यह पता चलता है कि स्क्रीन लॉक कितना लंबा या किस तरह का है. ऐप्लिकेशन उपयोगकर्ताओं को यह सुझाव भी दे सकता है कि वे स्क्रीन लॉक को एक तय लेवल तक अपडेट करें. लेकिन उपयोगकर्ता इसे बेझिझक अनदेखा करके छोड़ सकते हैं. ध्यान दें कि स्क्रीन लॉक को सादे टेक्स्ट में सेव नहीं किया जाता है इसलिए ऐप्लिकेशन को सटीक पासवर्ड पता नहीं होता है."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"बायोमीट्रिक हार्डवेयर इस्तेमाल करने दें"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"पुष्टि के लिए, ऐप्लिकेशन को बायोमीट्रिक हार्डवेयर इस्तेमाल करने की मंज़ूरी दें"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"उंगली की छाप के लिए हार्डवेयर को प्रबंधित करें"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"उंगली की छाप वाले टेम्पलेट का उपयोग करने के लिए जोड़ने और हटाने के लिए ऐप को विधियां प्रारंभ करने देती है."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"उंगली की छाप के लिए हार्डवेयर का उपयोग करें"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए उंगली की छाप हार्डवेयर का उपयोग करने देती है"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"फ़िंगरप्रिंट हार्डवेयर को प्रबंधित करें"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"फ़िंगरप्रिंट वाले टेम्पलेट का इस्तेमाल करने के लिए जोड़ने और हटाने के लिए ऐप को तरीके शुरू करने देती है."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"फ़िंगरप्रिंट हार्डवेयर का उपयोग करें"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए फ़िंगरप्रिंट हार्डवेयर का उपयोग करने देती है"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"अपने संगीत संग्रह में बदलाव करने की अनुमति दें"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"इससे ऐप्लिकेशन को आपके संगीत संग्रह में बदलाव करने की मंज़ूरी दी जाती है"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"अपने वीडियो संग्रह में बदलाव करने की अनुमति दें"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"पहचान नहीं हो पाई"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"प्रमाणीकरण रद्द किया गया"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"पिन, पैटर्न या पासवर्ड सेट नहीं है"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फ़िंगरप्रिंट की पहचान की गई. कृपया पुनः प्रयास करें."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"फ़िंगरप्रिंट की पहचान आंशिक तौर पर की गई. कृपया फिर से कोशिश करें."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फ़िंगरप्रिंट प्रोसेस नहीं हो सका. कृपया दोबारा कोशिश करें."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फ़िंगरप्रिंट सेंसर गंदा है. कृपया साफ़ करें और फिर कोशिश करें."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"उंगली बहुत तेज़ी से चलाई गई है. कृपया फिर से कोशिश करें."</string>
@@ -545,9 +543,9 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"चेहरे की पहचान की गई"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"चेहरे की पहचान की गई, कृपया पुष्टि बटन दबाएं"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को संग्रहित नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट निकालें."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय खत्म हो गया. पुनः प्रयास करें."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट क्रियान्वयन रोक दिया गया."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फ़िंगरप्रिंट को स्टोर नहीं किया जा सका. कृपया कोई मौजूदा फ़िंगरप्रिंट हटाएं."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय खत्म हो गया. फिर से कोशिश करें."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट ऑपरेशन रोक दिया गया."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"उपयोगकर्ता ने फिंगरप्रिंट की पुष्टि की कार्रवाई रद्द कर दी है."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"बहुत ज़्यादा प्रयास कर लिए गए हैं. बाद में फिर से प्रयास करें."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"बहुत ज़्यादा कोशिशें. फ़िंगरप्रिंट सेंसर अक्षम है."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ऐप को परेशान न करें कॉन्फ़िगरेशन पढ़ने और लिखने देती है."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"देखने की अनुमतियां चालू करें"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"इस्तेमाल करने वाले को किसी ऐप्लिकेशन के लिए अनुमतियों का इस्तेमाल शुरू करने देता है. सामान्य ऐप्लिकेशन के लिए इसकी ज़रूरत कभी नहीं पड़ती."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"सुलभता शॉर्टकट टारगेट"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"सुलभता शॉर्टकट टारगेट के बारे में बताने के लिए ऐप्लिकेशन को मंज़ूरी दें."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करना"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्‍क्रीन लॉक पासवर्ड और पिन की लंबाई और उनमें स्वीकृत वर्णों को नियंत्रित करना."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"स्‍क्रीन अनलॉक करने के की कोशिशों पर नज़र रखना"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 8ddd5f8..45c39f2 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogućuje primanje i obradu SMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primanje tekstnih poruka (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Aplikaciji omogućuje primanje i obradu MMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Prosljeđivanje poruka emitiranja na mobitele"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Omogućuje aplikaciji da se poveže s modulom za emitiranje na mobitele kako bi prosljeđivala poruke koje se emitiraju na mobitele po njihovom primitku. Upozorenja značajke emitiranja na mobitele dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno emitiranje na mobitele."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čitaj poruke koje se emitiraju unutar mobilne mreže"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogućuje aplikaciji čitanje poruka emitiranih unutar mobilne mreže koje prima vaš uređaj. Upozorenja koja se emitiraju na području mobilne mreže dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno upozorenje koje se emitira unutar mobilne mreže."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čitanje pretplaćenih feedova"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Omogućuje aplikaciji čitanje i pisanje konfiguracije opcije Ne ometaj."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"pokrenuti upotrebu dopuštenja za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Dopušta nositelju pokretanje upotrebe dopuštenja za aplikaciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj prečaca pristupačnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Aplikaciji omogućuje da definira cilj prečaca pristupačnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Nadziri pokušaje otključavanja zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d910025..aac2d76 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lehetővé teszi az alkalmazás számára, hogy SMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"szöveges üzenetek (MMS) fogadása"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Lehetővé teszi az alkalmazás számára, hogy MMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cellán belüli üzenetek továbbítása"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Az alkalmazás összekapcsolódhat a cellán belüli üzenetszórás moduljával, hogy az érkezésükkor továbbítani tudja a cellán belüli üzeneteket. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások vészhelyzeti cellaüzenet érkezésekor befolyásolhatják az eszköz teljesítményét és működését."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"cellán belüli üzenetek olvasása"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Lehetővé teszi az alkalmazás számára az eszközre érkező cellán belüli üzenetek olvasását. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások befolyásolhatják az eszköz  teljesítményét vagy működését vészhelyzeti cellaüzenet érkezésekor."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"feliratkozott hírcsatornák olvasása"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Az alkalmazás olvashatja és szerkesztheti a „Ne zavarjanak” funkció beállításait."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"engedélyhasználat megtekintésének elindítása"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Lehetővé teszi a felhasználó számára, hogy elindítsa az alkalmazás engedélyhasználatát. A normál alkalmazásoknak erre soha nincs szükségük."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"A kisegítő lehetőségek gyorsparancs célja"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Engedélyezi az alkalmazásoknak a kisegítő lehetőségek gyorsparancs céljának meghatározását."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"A képernyőzár jelszavaiban és PIN kódjaiban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Képernyőzár-feloldási kísérletek figyelése"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 6f5507f..a5b4e30 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -230,7 +230,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Վրիպակի զեկույց"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Ավարտել աշխատաշրջանը"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Սքրինշոթ"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Վրիպակների զեկույց"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Հաշվետվություն վրիպակի մասին"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Սա տեղեկություններ կհավաքագրի ձեր սարքի առկա կարգավիճակի մասին և կուղարկի այն էլեկտրոնային նամակով: Որոշակի ժամանակ կպահանջվի վրիպակի մասին զեկուցելու պահից սկսած մինչ ուղարկելը: Խնդրում ենք փոքր-ինչ համբերատար լինել:"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Ինտերակտիվ զեկույց"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Հիմնականում օգտագործեք այս տարբերակը: Այն ձեզ թույլ է տալիս հետևել զեկույցի ստեղծման գործընթացին, խնդրի մասին լրացուցիչ տեղեկություններ մուտքագրել և սքրինշոթներ ստեղծել: Կարող է բաց թողնել քիչ օգտագործվող որոշ բաժիններ, որոնց ստեղծումը երկար է տևում:"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Թույլ է տալիս հավելվածին ստանալ և մշակել SMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ստանալ տեքստային հաղորդագրություններ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Թույլ է տալիս հավելվածին ստանալ և մշակել MMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Բջջային հեռարձակման հաղորդագրությունների վերահասցեավորում"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Թույլ է տալիս հավելվածին կապ հաստատել բջջային հեռարձակման մոդուլի հետ՝ բնակչությանը ծանուցող հաղորդագրությունները վերահասցեավորելու համար։ Որոշ երկրներում այս հաղորդագրություններն օգտագործվում են բնակչությանը արտակարգ իրավիճակների մասին զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի աշխատանքին, որին ուղարկվում են այս հաղորդագրությունները:"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"կարդալ բջջային զեկուցվող հաղորդագրությունները"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքի կողմից ստացված բջջային հեռարձակվող հաղորդագրությունները: Բջջային հեռարձակվող զգուշացումները ուղարկվում են որոշ վայրերում` արտակարգ իրավիճակների մասին ձեզ զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի արդյունավետությանը կամ շահագործմանը, երբ ստացվում է արտակարգ իրավիճակի մասին բջջային հաղորդում:"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"կարդալ բաժանորդագրված հոսքերը"</string>
@@ -370,7 +368,7 @@
     <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Թույլ է տալիս հավելվածին միացնել մեքենայի ռեժիմը:"</string>
     <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"փակել այլ հավելվածները"</string>
     <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Թույլ է տալիս հավելվածին վերջ տալ այլ հավելվածների հետնաշերտի գործընթացները: Սա կարող է պատճառ դառնալ, որ այլ հավելվածները դադարեն աշխատել:"</string>
-    <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների վերևում"</string>
+    <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների վրայից"</string>
     <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Այս հավելվածը կարող է ցուցադրվել այլ հավելվածների կամ էկրանի այլ հատվածների վերևում: Դա կարող է խոչընդոտել հավելվածի նորմալ օգտագործմանը և փոխել այլ հավելվածների տեսքը:"</string>
     <string name="permlab_runInBackground" msgid="7365290743781858803">"աշխատել ֆոնում"</string>
     <string name="permdesc_runInBackground" msgid="7370142232209999824">"Այս հավելվածը կարող է աշխատել ֆոնային ռեժիմում և ավելի արագ սպառել մարտկոցի լիցքը։"</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Չհաջողվեց ճանաչել"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Նույնականացումը չեղարկվեց"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Ավելացրեք PIN կոդ, նախշ կամ գաղտնաբառ։"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Մատնահետքը հայտնաբերվել է մասամբ: Փորձեք նորից:"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Մատնահետքն ամբողջությամբ չի սկանավորվել: Փորձեք նորից:"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Չհաջողվեց մշակել մատնահետքը: Նորից փորձեք:"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Մատնահետքերի սենսորն աղտոտված է: Մաքրեք այն և փորձեք նորից:"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Շատ արագ անցկացրիք մատը: Փորձեք նորից:"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Թույլ է տալիս հավելվածին փոփոխել «Չանհանգստացնել» գործառույթի կազմաձևումը:"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"թույլտվությունների մասին տվյալների հասանելիություն"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Հավելվածին հասանելի կդառնան թույլտվությունների մասին տվյալները։ Այս թույլտվությունն անհրաժեշտ չէ սովորական հավելվածներին։"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"հատուկ գործառույթների դյուրանցումն օգտագործելու նպատակը"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Հավելվածին թույլ է տալիս որոշել հատուկ գործառույթների դյուրանցումն օգտագործելու նպատակը։"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Սահմանել գաղտնաբառի կանոնները"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Կառավարել էկրանի ապակողպման գաղտնաբառերի և PIN կոդերի թույլատրելի երկարությունն ու գրանշանները:"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
@@ -1387,8 +1383,8 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Ցուցադրում այլ հավելվածների վրայից"</string>
-    <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
-    <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
+    <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վրայից"</string>
+    <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վրայից"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string>
     <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Անջատել"</string>
     <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"<xliff:g id="NAME">%s</xliff:g> հիշասարքի ստուգում…"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Ավելի շատ ընտրանքներ"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Համօգտագործվող ներքին հիշողություն"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Ներքին ընդհանուր կրիչ"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD քարտ"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"SD քարտ <xliff:g id="MANUFACTURER">%s</xliff:g>-ից"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB սարքավար"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"Հերթական համարը`"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Մատնահետքերը`"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 մատնահետք`"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1մատնահետք`"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 մատնահետք`"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Տեսնել բոլորը"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Ընտրել գործունեությունը"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Կիսվել"</string>
@@ -2011,7 +2007,7 @@
     <string name="standby_warning_message" product="default" msgid="5222741828239073484">"Սարքը շուտով կանջատվի: Սեղմեք՝ միացրած թողնելու համար:"</string>
     <string name="notification_appops_camera_active" msgid="5050283058419699771">"Տեսախցիկ"</string>
     <string name="notification_appops_microphone_active" msgid="4335305527588191730">"Խոսափող"</string>
-    <string name="notification_appops_overlay_active" msgid="633813008357934729">"ցուցադրվում է մյուս հավելվածների վերևում"</string>
+    <string name="notification_appops_overlay_active" msgid="633813008357934729">"ցուցադրվում է մյուս հավելվածների վրայից"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2348803891571320452">"Ծանուցում լիցքավորման մասին"</string>
     <string name="dynamic_mode_notification_title" msgid="508815255807182035">"Մարտկոցի լիցքը կարող է սովորականից շուտ սպառվել"</string>
     <string name="dynamic_mode_notification_summary" msgid="2541166298550402690">"Մարտկոցի կյանքը երկարացնելու համար ակտիվացվել է մարտկոցի տնտեսման ռեժիմը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 88e396c..228da88 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -161,7 +161,7 @@
     <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Autentikasi via proxy server gagal."</string>
     <string name="httpErrorConnect" msgid="8714273236364640549">"Tidak dapat tersambung ke server."</string>
     <string name="httpErrorIO" msgid="2340558197489302188">"Tidak dapat berkomunikasi dengan server. Coba lagi nanti."</string>
-    <string name="httpErrorTimeout" msgid="4743403703762883954">"Sambungan ke server terputus."</string>
+    <string name="httpErrorTimeout" msgid="4743403703762883954">"Koneksi ke server terputus."</string>
     <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"Halaman ini berisi terlalu banyak pengalihan server."</string>
     <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Protokol tidak didukung."</string>
     <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Tidak dapat membuat sambungan aman."</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Memungkinkan aplikasi menerima dan memproses pesan SMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"terima pesan teks (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Memungkinkan aplikasi menerima dan memproses pesan MMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Teruskan pesan cell broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Mengizinkan aplikasi mem-binding ke modul cell broadcast untuk meneruskan pesan cell broadcast saat pesan tersebut diterima. Notifikasi cell broadcast dikirim di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu performa atau operasi perangkat saat cell broadcast darurat diterima."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"membaca pesan siaran seluler"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Mengizinkan aplikasi membaca pesan siaran seluler yang diterima perangkat Anda. Notifikasi siaran seluler dikirimkan di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu kinerja atau operasi perangkat Anda saat siaran seluler darurat diterima."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"baca feed langganan"</string>
@@ -519,7 +517,7 @@
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"kelola hardware sidik jari"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Mengizinkan aplikasi memanggil metode untuk menambahkan dan menghapus template sidik jari untuk digunakan."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"gunakan hardware sidik jari"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Mengizinkan aplikasi untuk menggunakan hardware sidik jari untuk otentikasi"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Mengizinkan aplikasi untuk menggunakan hardware sidik jari untuk autentikasi"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"memodifikasi koleksi musik Anda"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Mengizinkan aplikasi untuk memodifikasi koleksi musik Anda."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"memodifikasi koleksi video Anda"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Mengizinkan aplikasi membaca dan menulis konfigurasi status Jangan Ganggu."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"mulai melihat penggunaan izin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Memungkinkan pemegang memulai penggunaan izin untuk aplikasi. Tidak diperlukan untuk aplikasi normal."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"target pintasan aksesibilitas"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Mengizinkan aplikasi menentukan target pintasan aksesibilitas."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Mengontrol panjang dan karakter yang diizinkan dalam sandi dan PIN kunci layar."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Pantau upaya pembukaan kunci layar"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 32461d3..d0f8028 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Leyfir forriti að taka á móti og vinna úr SMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"taka á móti textaskilaboðum (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Leyfir forriti að taka á móti og vinna úr MMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Framsenda skilaboð frá endurvarpa"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Heimilar forritinu að bindast endurvarpseiningunni til að framsenda skilaboð frá endurvarpa þegar þau berast. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lesa skilaboð frá endurvarpa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Leyfir forriti að lesa skilaboð frá endurvarpa sem tækið móttekur. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lesa strauma í áskrift"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Leyfir forriti að lesa og skrifa í grunnstillingu „Ónáðið ekki“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"heimildanotkun upphafsyfirlits"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Leyfir handhafa að byrja heimildanotkun fyrir forrit. Ætti aldrei að þurfa fyrir venjuleg forrit."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"áfangastaður aðgengisflýtileiðar"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Leyfir forriti að skilgreina áfangastað aðgengisflýtileiðar."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setja reglur um aðgangsorð"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Stjórna lengd og fjölda stafa í aðgangsorðum og PIN-númerum skjáláss."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Fylgjast með tilraunum til að taka skjáinn úr lás"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6e25563..747d918 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -344,12 +344,10 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Consente all\'applicazione di ricevere ed elaborare messaggi SMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ricezione messaggi di testo (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Consente all\'applicazione di ricevere ed elaborare messaggi MMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Inoltro di messaggi cell broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Consente all\'app di essere associata al modulo di cell broadcast al fine di inoltrare i messaggi di cell broadcast man mano che arrivano. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lettura di messaggi cell broadcast"</string>
-    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le applicazioni dannose potrebbero interferire con il rendimento o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
+    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lettura feed sottoscritti"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Consente all\'applicazione di ottenere dettagli sui feed attualmente sincronizzati."</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"invio e visualizzazione di SMS"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Consente all\'app di leggere e modificare la configurazione della funzione Non disturbare."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"avvio dell\'uso dell\'autorizzazione di visualizzazione"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Consente al titolare di avviare l\'uso delle autorizzazioni per un\'app. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"target della scorciatoia Accessibilità"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Consente a un\'app di definire il target della scorciatoia Accessibilità"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Impostare regole per le password"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlla la lunghezza e i caratteri ammessi nelle password e nei PIN del blocco schermo."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorare tentativi di sblocco dello schermo"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"Numero di serie:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Fingerprint:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"Impronta SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Impronta SHA-1:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Fingerprint SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Mostra tutto"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Scegli attività"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Condividi con"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 6e61213..4c12e43 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -330,7 +330,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"קבע את המרחק מהתצוגה ואת מיקום התצוגה."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ביצוע תנועות"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"יכול להקיש, להחליק, לעשות תנועת צביטה ולבצע תנועות אחרות."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"תנועות"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"תנועות של טביעות אצבעות"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"השבת או שנה את שורת המצב"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏מאפשר לאפליקציה לקבל ולעבד הודעות SMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‏קבלת הודעות טקסט (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"‏מאפשר לאפליקציה לקבל ולעבד הודעות MMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"העברת הודעות של שידור סלולרי"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"מאפשרת לאפליקציה להתחייב למודול של השידור הסלולרי כדי להעביר הודעות של שידור סלולרי כשהן מתקבלות. התראות שידור סלולרי נשלחות במקומות מסוימים כדי להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר כאשר מתקבל שידור חירום סלולרי."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"קריאת הודעות שידור סלולרי"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"מאפשר לאפליקציה לקרוא הודעות שידור סלולרי שהתקבלו במכשיר שלך. התראות שידור סלולרי נשלחות במקומות מסוימים על מנת להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר שלך כאשר מתקבל שידור חירום סלולרי."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"קרא עדכוני מנויים"</string>
@@ -540,9 +538,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"לא זוהתה"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"האימות בוטל"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"עוד לא הוגדרו קוד גישה, קו ביטול נעילה או סיסמה"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"זוהתה טביעת אצבע חלקית. נסה שוב."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"זוהתה טביעת אצבע חלקית. אפשר לנסות שוב."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"לא ניתן היה לעבד את טביעת האצבע. נסה שוב."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"החיישן של טביעות האצבעות מלוכלך. נקה אותו ונסה שוב."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"החיישן של טביעות האצבעות מלוכלך. צריך לנקות אותו ולנסות שוב."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"הזזת את האצבע מהר מדי. נסה שוב."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"הזזת את האצבע לאט מדי. נסה שוב."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -550,9 +548,9 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"טביעת האצבע אומתה"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"זיהוי הפנים בוצע"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"זיהוי הפנים בוצע. יש ללחוץ על אישור"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"החומרה בשביל טביעת אצבע אינה זמינה."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"לא ניתן לאחסן טביעת אצבע. הסר טביעת אצבע קיימת."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"החומרה בשביל טביעות אצבעות אינה זמינה."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"לא ניתן לאחסן טביעת אצבע. יש להסיר טביעת אצבע קיימת."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. אפשר לנסות שוב."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"פעולת טביעת האצבע בוטלה."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"פעולת טביעת האצבע בוטלה בידי המשתמש."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"יותר מדי ניסיונות. נסה שוב מאוחר יותר."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"מאפשר לאפליקציה לקרוא ולכתוב את התצורה של \'נא לא להפריע\'."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"התחלת צפייה בהרשאות השימוש"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"מאפשרת לבעלים להפעיל את השימוש בהרשאות עבור אפליקציה מסוימת. הרשאה זו אף פעם לא נדרשת עבור אפליקציות רגילות."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"קיצור דרך ליעד של פעולת נגישות"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"מאפשרת לאפליקציה להגדיר את קיצור הדרך ליעד של פעולת נגישות."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"קביעת האורך הנדרש והתווים המותרים בסיסמאות ובקודי הגישה של מסך הנעילה."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"מעקב אחר ניסיונות לביטול של נעילת המסך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 15e10e4..98600b8 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMSメッセージの受信と処理をアプリに許可します。これにより、アプリがデバイスに届いたメッセージを表示することなく監視または削除できるようになります。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"テキストメッセージ(MMS)の受信"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMSメッセージの受信と処理をアプリに許可します。これにより、アプリがデバイスに届いたメッセージを表示することなく監視または削除できるようになります。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"緊急速報メールの転送"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"受信した緊急速報メールを転送するために、緊急速報メール モジュールにバインドすることをこのアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"緊急速報メール SMS の読み取り"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"デバイスで受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"登録したフィードの読み取り"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"サイレント モード設定の読み取りと書き込みをアプリに許可します。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"表示権限の使用の開始"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"アプリの権限使用の開始を所有者に許可します。通常のアプリでは不要です。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ユーザー補助ショートカットのターゲット"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ユーザー補助ショートカットのターゲットの定義付けをアプリに許可します。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"画面ロックのパスワードとPINの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"画面ロック解除試行の監視"</string>
@@ -1195,7 +1191,7 @@
     <string name="unsupported_display_size_show" msgid="7969129195360353041">"常に表示"</string>
     <string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g> は、互換性のない Android OS バージョン用にビルドされているため、予期しない動作が発生するおそれがあります。アプリの更新バージョンを利用できる場合があります。"</string>
     <string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"常に表示"</string>
-    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"アップデートをチェック"</string>
+    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"アップデートを確認"</string>
     <string name="smv_application" msgid="3307209192155442829">"アプリ「<xliff:g id="APPLICATION">%1$s</xliff:g>」(プロセス「<xliff:g id="PROCESS">%2$s</xliff:g>」)でStrictModeポリシー違反がありました。"</string>
     <string name="smv_process" msgid="5120397012047462446">"プロセス<xliff:g id="PROCESS">%1$s</xliff:g>でStrictModeポリシー違反がありました。"</string>
     <string name="android_upgrading_title" product="default" msgid="7513829952443484438">"スマートフォンの更新中…"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index a66d897..cc8ecc2 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"აპს შეეძლება SMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება თქვენ მოწყობილობაზე გამოგზავნილი შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ტექსტური შეტყობინებების (MMS) მიღება"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"აპს შეეძლება MMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cell broadcast შეტყობინებების გადამისამართება"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"საშუალებას აძლევს აპს, დაუკავშირდეს cell broadcast მოდულს იმისთვის, რომ გადაამისამართოს cell broadcast შეტყობინებები მათი მიღებისთანავე. Cell broadcast გაფრთხილებები მიეწოდება ზოგიერთ მდებარეობაზე საგანგებო სიტუაციების შესახებ გაფრთხილების მიზნით. საგანგებო cell broadcast-ის მიღების დროს, მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"მასიური დაგზავნის შეტყობინებების წაკითხვა"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"აპს შეეძლება, წაიკითხოს თქვენს მოწყობილობაზე გამოგზავნილი ქსელის სამაუწყებლო შეტყობინებები. სამაუწყებლო გაფრთხილებები მოგეწოდებათ ზოგიერთ ადგილზე ექსტრემალური სიტუაციების შესახებ გასაფრთხილებლად. ქსელის გადაუდებელი შეტყონიბენის მიღების დროს მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"გამოწერილი არხების წაკითხვა"</string>
@@ -517,9 +515,9 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ბიომეტრიული აპარატის გამოყენება"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"საშუალებას აძლევს აპს, ავტორიზაციისთვის გამოიყენოს ბიომეტრიული აპარატი"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"თითის ანაბეჭდის აპარატის მართვა"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"საშუალებას აძლევს აპლიკაციას დაამატოს ან ამოშალოს გამოსაყენებელი თითის ანაბეჭდის ნიმუშები,"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"საშუალებას აძლევს აპლიკაციას დაამატოს ან ამოშალოს გამოსაყენებელი თითის ანაბეჭდის ნიმუშები."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"თითის ანაბეჭდის აპარატის გამოყენება"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"საშუალებას აძლევს აპლიკაციას გამოიყენოს ავტენთიფიკაციისათვის თითის ანაბეჭდის აპარატი"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"საშუალებას აძლევს აპლიკაციას ავტორიზაციისთვის გამოიყენოს თითის ანაბეჭდის აპარატი"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"თქვენი მუსიკალური კოლექციის შეცვლა"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"აპი შეძლებს თქვენი მუსიკალური კოლექციის შეცვლას."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"თქვენი ვიდეოკოლექციის შეცვლა"</string>
@@ -535,7 +533,7 @@
     <string name="biometric_error_canceled" msgid="349665227864885880">"ავტორიზაცია გაუქმდა"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"PIN-კოდი, ნიმუში ან პაროლი დაყენებული არ არის"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"აღმოჩენილია თითის ნაწილობრივი ანაბეჭდი. გთხოვთ, სცადოთ ხელახლა."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"თითის ანაბეჭდი ვერ მუშავდება. გთხოვთ, სცადოთ ხელახლა."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"თითის ანაბეჭდის დამუშავება ვერ მოხერხდა. გთხოვთ, ცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"თითის ანაბეჭდის სენსორი დაბინძურებულია. გთხოვთ, გაასუფთაოთ და სცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"თითის აღება მეტისმეტად სწრაფად მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"თითის აღება მეტისმეტად ნელა მოხდა. გთხოვთ, სცადოთ ხელახლა."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"საშუალებას აძლევს აპს, წაიკითხოს და დაწეროს კონფიგურაცია „არ შემაწუხოთ“."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ნახვის ნებართვის გამოყენების დაწყება"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"მფლობელს საშუალებას აძლევს, დაიწყოს აპის ნებართვის გამოყენება. ჩვეულებრივი აპებისთვის არასოდეს უნდა იყოს საჭირო."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"მარტივი წვდომის მალსახმობის სამიზნე"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"აპს აძლევს მარტივი წვდომის მალსახმობის სამიზნის განსაზღვრის საშუალებას."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"პაროლის წესების დაყენება"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"აკონტროლეთ ეკრანის ბლოკირების პაროლებისა და PIN-ების სიმბოლოების სიგრძე."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ეკრანის განბლოკვის მცდელობების მონიტორინგი"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index af6b788..db9fad2 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Қолданбаға SMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"мәтін хабарларын алу (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Қолданбаға MMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Ұялы таратылым хабарларының бағытын өзгерту"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ұялы таратылым хабарлары алынғаннан кейін, олардың бағытын өзгерту үшін қолданбаға ұялы таратылым модулімен байланыстыруға мүмкіндік береді. Ұялы таратылым ескертулері кей аймақтарда төтенше жағдайлар туралы хабарлау үшін беріледі. Төтенше жағдай туралы ұялы таратылым хабары алынғаннан кейін, зиянды қолданбалар құрылғы жұмысына кедергі келтіруі мүмкін."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ұялы хабар тарату хабарларын оқу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Қолданбаға ұялы таратылым хабарларын оқу мүмкіндігін береді. Ұялы таратылым дабылдары кейбір аймақтарда төтенше жағдай туралы ескерту үшін қолданылады. Төтенше ұялы хабарлар келгенде залалды қолданбалар құрылғының жұмысына кедергі жасауы мүмкін."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"жазылған ағындарды оқу"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Қолданбаға «Мазаламау» конфигурациясын оқу және жазу мүмкіндігін береді."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"рұқсаттарды пайдалану туралы деректерді көру"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Пайдаланушы қолданбаға берілетін рұқсаттарды басқара алады. Ондай рұқсаттар әдеттегі қолданбаларға керек емес."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"арнайы мүмкіндіктер таңбашасының мақсаты"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Қолданбаға арнайы мүмкіндіктер таңбашасының мақсатын анықтауға мүмкіндік береді."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Құпия сөз ережелерін тағайындау"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Экран бекітпесінің құпия сөздерінің және PIN кодтарының ұзындығын және оларда рұқсат етілген таңбаларды басқару."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Экран құлпын ашу әркеттерін бақылау"</string>
@@ -1556,7 +1552,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Басқа опциялар"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Ішкі ортақ қойма"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Ішкі ортақ жад"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD картасы"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD картасы"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB дискі"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index cf9b9d2..021da3e 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ធ្វើកាយវិការ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"អាចប៉ះ អូស ច្បិច និងធ្វើកាយវិការផ្សេងទៀត"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ចលនា​ស្នាមម្រាមដៃ"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"អាចថត​ចលនា​ដែលមាន​សកម្មភាព​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍បាន។"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"អាចចាប់យក​ចលនា​ដែលធ្វើនៅលើ​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍បាន។"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"បិទ ឬ​កែ​របារ​ស្ថានភាព"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ធ្វើជារបារស្ថានភាព"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ឲ្យ​កម្មវិធី​ទទួល និង​ដំណើរការ​​សារ MMS ។ មាន​ន័យ​ថា កម្មវិធី​អាច​ត្រួតពិនិត្យ​ ឬ​លុប​សារ​ដែល​បាន​ផ្ញើ​ទៅ​ឧបករណ៍​របស់​អ្នក ដោយ​​មិន​បង្ហាញ​អ្នក។"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ទទួល​សារ​អត្ថបទ (MMS​)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ឲ្យ​កម្មវិធី​ទទួល និង​ដំណើរការ​​សារ​ MMS ។ វា​មាន​ន័យ​ថា កម្មវិធី​អាច​តាមដាន​ ឬ​លុប​សារ​ដែល​បាន​ផ្ញើ​ទៅ​ឧបករណ៍​របស់​អ្នក​ដោយ​មិន​បង្ហាញ​ពួកវា។"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"បញ្ជូន​សារ​ផ្សាយចល័ត​បន្ត"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"អនុញ្ញាតឱ្យ​កម្មវិធី​ភ្ជាប់ទៅ​ម៉ូឌុល​ការផ្សាយចល័ត ដើម្បីបញ្ជូន​សារផ្សាយ​ចល័តបន្ត នៅពេល​ទទួលបាន​សារទាំងនោះ។ ការជូនដំណឹងអំពី​ការផ្សាយចល័ត​ត្រូវបានបញ្ជូនទៅ​ទីតាំងមួយចំនួន ដើម្បីព្រមាន​អ្នក​អំពីស្ថានភាព​អាសន្ន។ កម្មវិធី​គ្រោះថ្នាក់​អាច​រំខាន​ដល់ដំណើរការ ឬប្រតិបត្តិការ​ឧបករណ៍​របស់អ្នក នៅពេល​ទទួលបានការផ្សាយ​ចល័តពេលមានអាសន្ន​។"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"អាន​សារ​ប្រកាស​ចល័ត"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ឲ្យ​កម្មវិធី​អាន​សារ​ប្រកាស​ការ​ហៅ​ដែល​ឧបករណ៍​របស់​​អ្នក​បាន​ទទួល។ ការ​ជូន​ដំណឹង​ប្រកាស​ចល័ត​ត្រូវ​បាន​បញ្ជូន​ទៅ​ទីតាំង​មួយ​ចំនួន ដើម្បី​ព្រមាន​អ្នក​អំពី​ស្ថានភាព​អាសន្ន។ កម្មវិធី​ព្យាបាទ​អាច​ជ្រៀតជ្រែក​ការ​អនុវត្ត ឬ​ប្រតិបត្តិការ​ឧបករណ៍​របស់​អ្នក​​ពេល​ទទួល​ការ​ប្រកាស​ចល័ត​ពេល​អាសន្ន។"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"អាន​អត្ថបទ​ព័ត៌មាន​បាន​ជាវ"</string>
@@ -517,7 +515,7 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ប្រើ​ឧបករណ៍​ស្កេន​ស្នាមម្រាមដៃ"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"អនុញ្ញាត​ឱ្យ​កម្មវិធី​ប្រើ​ឧបករណ៍​ស្កេន​ស្នាមម្រាមដៃ​សម្រាប់​ការផ្ទៀងផ្ទាត់"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"គ្រប់គ្រងផ្នែករឹងស្នាមម្រាមដៃ"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"អនុញ្ញាតឲ្យកម្មវិធីប្រើវិធីសាស្ត្របន្ថែម និងលុបពុម្ពម្រាមដៃសម្រាប់ប្រើប្រាស់។"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"អនុញ្ញាតឲ្យកម្មវិធីប្រើវិធីនានា ដើម្បីបញ្ចូល និងលុបទម្រង់គំរូស្នាមម្រាមដៃសម្រាប់ប្រើប្រាស់។"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ប្រើផ្នែករឹងស្នាមម្រាមដៃ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"អនុញ្ញាតឲ្យកម្មវិធីប្រើផ្នែករឹងស្នាមម្រាមដៃសម្រាប់ការផ្ទៀងផ្ទាត់"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"កែប្រែ​បណ្ដុំ​តន្ត្រី​របស់​អ្នក"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"គ្មាន​ការកំណត់​កូដ pin លំនាំ ឬពាក្យសម្ងាត់​ទេ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"បានផ្តិតយកស្នាមម្រាមដៃមិនពេញលក្ខណៈ។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ឧបករណ៍ផ្តិតម្រាមដៃប្រឡាក់ហើយ។ សូមសម្អាត ហើយព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ឧបករណ៍ចាប់ស្នាមម្រាមដៃគឺប្រឡាក់។ សូមសម្អាត រួចព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"ម្រាមដៃផ្លាស់ទីលឿនពេក។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ចលនាម្រាមដៃយឺតពេកហើយ។ សូមព្យាយាមម្តងទៀត។"</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -546,7 +544,7 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"បានផ្ទៀងផ្ទាត់​មុខ សូម​ចុច​បញ្ជាក់"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ផ្នែករឹងស្នាមម្រាមដៃមិនមានទេ។"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"មិនអាចផ្ទុកស្នាមម្រាមដៃទេ។ សូមយកស្នាមម្រាមដៃដែលមានស្រាប់ចេញ។"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ស្នាមម្រាមដៃបានអស់ម៉ោង។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ប្រតិបត្តិការ​ស្នាម​ម្រាម​ដៃ​ត្រូវ​បាន​បោះ​បង់​ដោយ​អ្នក​ប្រើប្រាស់។"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
@@ -557,7 +555,7 @@
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ម្រាមដៃ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"រូបតំណាងស្នាមម្រាមដៃ"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"រូបស្នាមម្រាមដៃ"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"គ្រប់គ្រង​ហាតវែរ​ដោះសោតាមទម្រង់មុខ"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"អនុញ្ញាតឱ្យកម្មវិធីប្រើវិធីសាស្ត្រដើម្បី​បញ្ចូល និងលុបទម្រង់​គំរូ​ផ្ទៃមុខសម្រាប់ប្រើប្រាស់។"</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"ប្រើ​ហាតវែរ​ដោះសោ​តាមទម្រង់មុខ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"អនុញ្ញាតឲ្យកម្មវិធីអាន និងសរសេរការកំណត់រចនាសម្ព័ន្ធមុខងារ កុំរំខាន។"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ចាប់ផ្ដើម​មើល​ការប្រើប្រាស់​ការអនុញ្ញាត"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"អនុញ្ញាត​ឱ្យម្ចាស់​ចាប់ផ្ដើម​ការប្រើប្រាស់​ការអនុញ្ញាត​សម្រាប់កម្មវិធី។ មិនគួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"គោលដៅផ្លូវកាត់ភាពងាយស្រួល"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"អនុញ្ញាតឱ្យ​កម្មវិធី​កំណត់​គោលដៅ​ផ្លូវកាត់​ភាពងាយស្រួល។"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"គ្រប់គ្រងប្រវែង និងតួអក្សរដែលអនុញ្ញាតឲ្យប្រើក្នុងពាក្យសម្ងាត់ និងលេខសម្ងាត់ចាក់សោអេក្រង់។"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"តាមដាន​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
@@ -1167,7 +1163,7 @@
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"សម្អាត​លំនាំដើម​ក្នុង​ការកំណត់​ប្រព័ន្ធ &gt; កម្មវិធី &gt; ទាញ​យក។"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព​​"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ជ្រើស​កម្មវិធី​សម្រាប់​ឧបករណ៍​យូអេសប៊ី"</string>
-    <string name="noApplications" msgid="2991814273936504689">"គ្មាន​កម្មវិធី​អាច​អនុវត្ត​សកម្មភាព​នេះ។"</string>
+    <string name="noApplications" msgid="2991814273936504689">"មិន​មាន​​កម្មវិធី​ដែលអាចធ្វើ​សកម្មភាពនេះ​បាន​ទេ។"</string>
     <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> បានឈប់"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> បានឈប់"</string>
     <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ឈប់ដំណើរការម្តងហើយម្តងទៀត"</string>
@@ -1520,7 +1516,7 @@
     <string name="sync_do_nothing" msgid="3743764740430821845">"មិន​ធ្វើអ្វី​ទេ​ឥឡូវ"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"ជ្រើស​គណនី"</string>
     <string name="add_account_label" msgid="2935267344849993553">"បញ្ចូល​គណនី​"</string>
-    <string name="add_account_button_label" msgid="3611982894853435874">"បន្ថែម​គណនី"</string>
+    <string name="add_account_button_label" msgid="3611982894853435874">"បញ្ចូល​គណនី"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"បង្កើន"</string>
     <string name="number_picker_decrement_button" msgid="476050778386779067">"បន្ថយ"</string>
     <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> ប៉ះ និងសង្កត់ឲ្យជាប់"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 028d563..edcb6d1 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -324,8 +324,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ಪ್ರದರ್ಶನದ ಝೂಮ್ ಮಟ್ಟ ಮತ್ತು ಸ್ಥಾನ ನಿರ್ಧಾರವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ಗೆಸ್ಚರ್‌ಗಳನ್ನು ಮಾಡಿ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್‌ಗಳನ್ನು ಮಾಡಬಹುದು."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಸೂಚಕಗಳು"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಸೂಚಕಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಗೆಶ್ಚರ್‌ಗಳು"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಗೆಶ್ಚರ್‌ಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ಪಠ್ಯ ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ಫಾರ್ವರ್ಡ್ ಮಾಡಿ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ಸೆಲ್ ಪ್ರಸಾರವು ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿದ ರೀತಿಯಲ್ಲಿಯೇ ಫಾರ್ವರ್ಡ್ ಮಾಡಲು, ಸೆಲ್ ಪ್ರಸಾರ ಮಾಡ್ಯುಲ್‌ ಅನ್ನು ಪ್ರತಿಬಂಧಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ತುರ್ತು ಸ್ಥಿತಿಗಳ ಕುರಿತು ನಿಮಗೆ ಎಚ್ಚರಿಸಲು ಸೆಲ್ ಪ್ರಸಾರದ ಎಚ್ಚರಿಕೆಗಳನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತದೆ. ತುರ್ತು ಸೆಲ್‌ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸಿದಾಗ ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಾಚರಣೆ ಅಥವಾ ಕಾರ್ಯಕ್ಷಮತೆಗೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್‌ಗಳು ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ಸೆಲ್ ಪ್ರಸಾರದ ಸಂದೇಶಗಳನ್ನು ಓದಿರಿ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ನಿಮ್ಮ ಸಾಧನದಿಂದ ಸ್ವೀಕರಿಸಿದ ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸೆಲ್ ಪ್ರಸಾರ ಎಚ್ಚರಿಕೆಗಳನ್ನು ತುರ್ತು ಸಂದರ್ಭಗಳಲ್ಲಿ ನಿಮಗೆ ಎಚ್ಚರಿಸುವ ಸಲುವಾಗಿ ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ವಿತರಿಸಲಾಗುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‌‌‌ಗಳು ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸುವಾಗ, ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆ ಇಲ್ಲವೇ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ಚಂದಾದಾರ ಫೀಡ್‌ಗಳನ್ನು ಓದಿ"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"ಆ್ಯಪ್‌ಗೆ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಸಂಕೀರ್ಣತೆ ಮಟ್ಟವನ್ನು (ಅಧಿಕ, ಮಧ್ಯಮ, ಕಡಿಮೆ ಅಥವಾ ಯಾವುದೂ ಅಲ್ಲ) ತಿಳಿದುಕೊಳ್ಳಲು ಅನುಮತಿಸುತ್ತದೆ, ಅದು ಉದ್ದದ ಸಂಭವನೀಯ ಶ್ರೇಣಿ ಮತ್ತು ಸ್ಕ್ರೀನ್ ಲಾಕ್‌ನ ವಿಧವನ್ನು ಸೂಚಿಸುತ್ತದೆ. ಬಳಕೆದಾರರು ನಿರ್ದಿಷ್ಟ ಹಂತದವರೆಗೆ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಬಹುದು, ಆದರೆ ಅವರು ಅದನ್ನು ನಿರ್ಲಕ್ಷಿಸಬಹುದು ಮತ್ತು ಅದರಿಂದ ಹೊರಬರಬಹುದು ಎಂಬುದನ್ನು ಸಹ ಆ್ಯಪ್ ಬಳಕೆದಾರರಿಗೆ ಸೂಚಿಸುತ್ತದೆ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಪಠ್ಯದ ರೂಪದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವುದಿಲ್ಲ, ಇದರಿಂದಾಗಿ ಆ್ಯಪ್‌ಗೆ ಸರಿಯಾದ ಪಾಸ್‌ವರ್ಡ್ ಗೊತ್ತಿರುವುದಿಲ್ಲ ಎಂಬುದನ್ನು ಗಮನಿಸಿ."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ಬಯೋಮೆಟ್ರಿಕ್ ಹಾರ್ಡ್‌ವೇರ್‌ ಬಳಸಿ"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಬಯೋಮೆಟ್ರಿಕ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ನಿರ್ವಹಿಸಿ"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ಬಳಕೆಗೆ ಬೆರಳಚ್ಚು ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ನಿರ್ವಹಿಸಿ"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ಬಳಕೆಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಲು ಆ್ಯಪ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"ನಿಮ್ಮ ಸಂಗೀತ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"ನಿಮ್ಮ ವೀಡಿಯೊ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಿ"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"ಪ್ರಮಾಣೀಕರಣವನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"ಪಿನ್, ಪ್ಯಾಟರ್ನ್ ಅಥವಾ ಪಾಸ್‌ವರ್ಡ್ ಸೆಟ್ ಮಾಡಿಲ್ಲ"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ಭಾಗಶಃ ಬೆರಳಚ್ಚು ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ಬೆರಳಚ್ಚು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ಬೆರಳಚ್ಚು ಸೆನ್ಸರ್ ಮಲಿನಗೊಂಡಿದೆ. ದಯವಿಟ್ಟು ಅದನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ಭಾಗಶಃ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಮಲಿನಗೊಂಡಿದೆ. ದಯವಿಟ್ಟು ಅದನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"ಬೆರಳನ್ನು ಅತಿ ವೇಗವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ಬೆರಳನ್ನು ತುಂಬಾ ನಿಧಾನವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -544,20 +542,20 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಮಾಣೀಕರಣ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ, ದೃಢೀಕರಣವನ್ನು ಒತ್ತಿ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ಬೆರಳಚ್ಚು ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ಬೆರಳಚ್ಚು ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಬೆರಳಚ್ಚು ತೆಗೆದುಹಾಕಿ."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಬೆರಳಚ್ಚು ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ಬೆರಳಚ್ಚು ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ಬಳಕೆದಾರರಿಂದ ಫಿಂಗರ್‌ ಫ್ರಿಂಟ್‌ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಲಾಗಿದೆ."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸಂಗ್ರಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಿ."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ಬಳಕೆದಾರರು ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಿದ್ದಾರೆ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್‌ ಫ್ರಿಂಟ್‌ ಸೆನ್ಸಾರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"ಯಾವುದೇ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಅನ್ನು ನೋಂದಣಿ ಮಾಡಿಲ್ಲ."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ಈ ಸಾಧನವು ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಹೊಂದಿಲ್ಲ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ಫಿಂಗರ್ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ಬೆರಳಚ್ಚು ಐಕಾನ್"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"ಫೇಸ್ ಅನ್‌ಲಾಕ್ ಹಾರ್ಡ್‌ವೇರ್ ಅನ್ನು ನಿರ್ವಹಿಸಿ"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"ಬಳಕೆಗೆ ಮುಖದ ಟೆಂಪ್ಲೇಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"ಫೇಸ್ ಅನ್‌ಲಾಕ್ ಹಾರ್ಡ್‌ವೇರ್ ಬಳಸಿ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಓದಲು ಮತ್ತು ಬರೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ವೀಕ್ಷಣಾ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ಆ್ಯಪ್‌ಗಾಗಿ ಅನುಮತಿ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಹೊಂದಿರುವವರಿಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಆ್ಯಪ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಟಾರ್ಗೆಟ್‌"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಟಾರ್ಗೆಟ್‌ ಅನ್ನು ವಿವರಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ಪಾಸ್‌ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ಪರದೆ ಲಾಕ್‌ನಲ್ಲಿನ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಿನ್‌ಗಳ ಅನುಮತಿಸಲಾದ ಅಕ್ಷರಗಳ ಪ್ರಮಾಣವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ಪರದೆಯ ಅನ್‌ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ"</string>
@@ -1589,7 +1585,7 @@
     <string name="serial_number" msgid="758814067660862493">"ಕ್ರಮ ಸಂಖ್ಯೆ:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್‌ಗಳು:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ಬೆರಳಚ್ಚು:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ಬೆರಳಚ್ಚು:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ಫಿಂಗರ್‌ಪ್ರಿಂಟ್:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ಚಟುವಟಿಕೆಯನ್ನು ಆರಿಸಿ"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f81cc00..2f06bee 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"앱이 SMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"문자 메시지 받기(MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"앱이 MMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"셀 브로드캐스트 메시지 전달"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"셀 브로드캐스트 메시지를 수신하자마자 전달하기 위해 앱이 셀 브로드캐스트 모듈에 연결하도록 허용합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"셀 브로드캐스트 메시지 읽기"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"앱이 기기가 수신한 셀 브로드캐스트 메시지를 읽을 수 있도록 합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"가입된 피드 읽기"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"앱에서 방해 금지 모드 설정을 읽고 작성하도록 허용합니다."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"권한 사용 보기 시작"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"앱의 권한 사용을 시작하려면 보유자를 허용하세요. 일반 앱에는 필요하지 않습니다."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"접근성 단축키 대상"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"앱이 접근성 단축키 대상을 정의할 수 있도록 허용합니다."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"화면 잠금 비밀번호와 PIN에 허용되는 길이와 문자 수를 제어합니다."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"화면 잠금 해제 시도 모니터링"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c61992c..2353ed0 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Колдонмого SMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"билдирүүлөрдү (MMS) кабыл алуу"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Колдонмого MMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Уюк жөнөтүүлөрүнүн билдирүүлөрүн башка номерге багыттоо"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Уюк жөнөтүүлөрүнүн билдирүүлөрү келген сайын башка номерге багыттап туруу үчүн колдонмого уюк жөнөтүүлөрүнүн модулу менен байланышууга уруксат берет. Шашылыш уюк жөнөтүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралуу сизге эскертүү үчүн жөнөтүлөт. Зыянкеч колдонмолор шашылыш уюк жөнөтүүлөрү кабыл алынганда түзмөктүн майнаптуулугуна же иштешине жолтоо болушу мүмкүн."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"уюктук берүү билдирүүлөрүн окуу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Колдонмого түзмөгүңүз кабыл алган уюк берүүнүн билдирүүлөрүн окууга жол берет. Шашылыш эскертүү билдирүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралу сизди эскертүү үчүн жөнөтүлөт. Зыяндуу колдономолор шашылыш эскертүүлөр берилип жатканда, сиздин түзмөктүн иштешине жолтоо болушу мүмкүн."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"жазылган түрмөктөрдү окуу"</string>
@@ -541,14 +539,14 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Манжа өтө жай жылды. Кайра аракет кылыңыз."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Манжа изинин аныктыгы текшерилди"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Манжа изи текшерилди"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Жүздүн аныктыгы текшерилди"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Жүздүн аныктыгы текшерилди, эми \"Ырастоону\" басыңыз"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Манжа изинин аппараттык камсыздоосу жеткиликтүү эмес."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Манжа изин сактоо мүмкүн эмес. Учурдагы манжа изин алып салыңыз."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Манжа изи иш-аракети жокко чыгарылды."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Манжа изи менен аныктыгын текшерүүнү колдонуучу жокко чыгарды."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Манжа изи операциясын колдонуучу жокко чыгарды."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Өтө көп жолу аракет жасадыңыз. Манжа изинин сенсору өчүрүлдү."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Кайра бир аракеттениңиз."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Колдонмого \"Тынчымды алба\" режиминин конфигурациясын окуу жана жазуу мүмкүнчүлүгүн берет."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"уруксаттын колдонулушун көрүп баштоо"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Колдонмонун пайдаланылышына уруксат берүүгө мүмкүнчүлүк берет. Кадимки колдонмолорго эч качан талап кылынбашы керек."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"максаттуу атайын мүмкүнчүлүк аракетине кыска жол"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Колдонмого максаттуу атайын мүмкүнчүлүк аракетине кыска жолду аныктоого уруксат берет."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Сырсөз эрежелерин коюу"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Экран кулпусунун сырсөздөрү менен PIN\'дерине уруксат берилген узундук менен белгилерди көзөмөлдөө."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Экран кулпусун ачуу аракеттерин көзөмөлдөө"</string>
@@ -1591,7 +1587,7 @@
     <string name="fingerprints" msgid="4516019619850763049">"Манжа издери:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 манжа изи:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 манжа изи:"</string>
-    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Бардыгын көрүү"</string>
+    <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Баарын көрүү"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Аракетти тандаңыз"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Төмөнкү менен бөлүшүү"</string>
     <string name="sending" msgid="3245653681008218030">"Жөнөтүлүүдө…"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index fb3afb3..a83fae1 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ອະນຸຍາດໃຫ້ແອັບຯຮັບ ແລະປະມວນຜົນຂໍ້ຄວາມ SMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ຮັບຂໍ້ຄວາມ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ອະນຸຍາດໃຫ້ແອັບຯ ຮັບແລະປະມວນຜົນຂໍ້ຄວາມ MMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ອະນຸຍາດໃຫ້ແອັບຜູກມັດກັບໂມດູນການກະຈາຍສັນຍານໂທລະສັບເພື່ອສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບເມື່ອໄດ້ຮັບມາ. ການເຕືອນການກະຈາຍສັນຍານໂທລະສັບແມ່ນຖືກຈັດສົ່ງໃນບາງສະຖານທີ່ເພື່ອເຕືອນທ່ານໃນກໍລະນີມີເຫດການສຸກເສີນເກີດຂຶ້ນ. ແອັບທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼື ການເຮັດວຽກຂອງອຸປະກອນທ່ານເມື່ອໄດ້ຮັບການກະຈາຍສັນຍານໂທລະສັບສຸກເສີນ."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ອ່ານຂໍ້ຄວາມກະຈາຍສັນຍານຂອງເສົາສັນຍານ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດອ່ານຂໍ້ຄວາມແຈ້ງເຕືອນເຫດສຸກເສີນ ທີ່ໄດ້ຮັບໂດຍອຸປະກອນຂອງທ່ານ. ການແຈ້ງເຕືອນສຸກເສີນທີ່ມີໃຫ້ບໍລິການໃນບາງພື້ນທີ່ ເພື່ອແຈ້ງເຕືອນໃຫ້ທ່ານຮູ້ເຖິງສະຖານະການສຸກເສີນ. ແອັບພລິເຄຊັນທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼືການດຳເນີນງານຂອງອຸປະກອນຂອງທ່ານ ເມື່ອໄດ້ການຮັບແຈ້ງເຕືອນສຸກເສີນຈາກສະຖານີມືຖື."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ອ່ານຂໍ້ມູນຟີດທີ່ສະໝັກໄວ້"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ອະນຸຍາດ​​ໃຫ້​ແອັບ​ອ່ານ​ ​ແລະ​ຂຽນການກນຳ​ດຄ່າ ບໍ່​ລົບ​ກວນ."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ເລີ່ມການໃຊ້ສິດອະນຸຍາດການເບິ່ງ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ອະນຸຍາດໃຫ້ຜູ້ຖືເລີ່ມການໃຊ້ສິດອະນຸຍາດສຳລັບແອັບໃດໜຶ່ງໄດ້. ແອັບປົກກະຕິບໍ່ຄວນຕ້ອງໃຊ້."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ເປົ້າໝາຍທາງລັດການຊ່ວຍເຂົ້າເຖິງ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ອະນຸຍາດໃຫ້ແອັບລະບຸເປົ້າໝາຍທາງລັດການຊ່ວຍເຂົ້າເຖິງ."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ຄວບຄຸມຄວາມຍາວ ແລະຕົວອັກສອນທີ່ອະ​ນຸ​ຍາດ​ໃຫ້​ຢູ່​ໃນລະ​ຫັດລັອກໜ້າຈໍ ແລະ PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index be9e32f..fdd5d2a 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Leidžiama programai gauti ir apdoroti SMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"gauti teksto pranešimus (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Leidžiama programai gauti ir apdoroti MMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Persiųsti mobiliuoju transliuojamus pranešimus"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Programai leidžiama susaistyti transliacijos mobiliuoju modulį, kad būtų galima persiųsti mobiliuoju transliuojamus pranešimus, kai jie gaunami. Transliacijos mobiliuoju įspėjimai pristatomi kai kuriose vietovėse, kad būtų galima įspėti apie kritines situacijas. Kai gaunamas mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"skaityti mobiliuoju transliuojamus pranešimus"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Programai leidžiama skaityti mobiliuoju transliuojamus pranešimus, gaunamus jūsų įrenginyje. Mobiliuoju transliuojami įspėjimai pristatomi kai kuriose vietose, kad įspėtų apie kritines situacijas. Kai gaunamas  mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"skaityti prenumeruojamus tiekimus"</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Leidžiama programai skaityti ir rašyti „Do Not Disturb“ konfigūraciją."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"pradėti peržiūrėti leidimo naudojimą"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Leidžia savininkui pradėti naudoti programos leidimą. Įprastoms programoms to neturėtų prireikti."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"pritaikomumo sparčiojo klavišo tikslas"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Programai leidžiama apibrėžti pritaikomumo sparčiojo klavišo tikslą."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Valdykite, kokio ilgio ekrano užrakto slaptažodžius ir PIN kodus galima naudoti."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Stebėti bandymus atrakinti ekraną"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 89575c6..d1b7764 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ļauj lietotnei saņemt un apstrādāt īsziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"saņemt ziņojumus (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ļauj lietotnei saņemt un apstrādāt multiziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Pārsūtīt šūnu apraides ziņojumus"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ļauj piesaistīt lietotni šūnu apraides modulim, lai pārsūtītu šūnu apraides ziņojumus, tiklīdz tie tiek saņemti. Šūnu apraides brīdinājumi tiek piegādāti noteiktās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"šūnu apraides ziņojumu lasīšana"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ļauj lietotnei lasīt ierīcē saņemtos šūnu apraides ziņojumus. Šūnu apraides brīdinājumi tiek piegādāti dažās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lasīt abonētās plūsmas"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ļauj lietotnei lasīt un rakstīt režīma “Netraucēt” konfigurāciju."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Datu skatīšana par izmantojamajām atļaujām"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ļauj atļaujas īpašniekam sākt lietotnes atļauju izmantošanu. Parastām lietotnēm tas nekad nav nepieciešams."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"pieejamības īsinājumtaustiņa mērķis"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ļauj lietotnei definēt pieejamības īsinājumtaustiņa mērķi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolēt ekrāna bloķēšanas paroļu un PIN garumu un tajos atļautās rakstzīmes."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
diff --git a/core/res/res/values-mcc310-mnc030-da/strings.xml b/core/res/res/values-mcc310-mnc030-da/strings.xml
index c45e3be..3dbda05 100644
--- a/core/res/res/values-mcc310-mnc030-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc030-da/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="2995576894416087107">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc170-da/strings.xml b/core/res/res/values-mcc310-mnc170-da/strings.xml
index 8580fb3..6a4d3e8 100644
--- a/core/res/res/values-mcc310-mnc170-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc170-da/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="3173546391131606065">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc280-da/strings.xml b/core/res/res/values-mcc310-mnc280-da/strings.xml
index 6a8e40b..919ac32 100644
--- a/core/res/res/values-mcc310-mnc280-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc280-da/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="822496463303720579">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc380-da/strings.xml b/core/res/res/values-mcc310-mnc380-da/strings.xml
index cd4c796..8b8ac1a 100644
--- a/core/res/res/values-mcc310-mnc380-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc380-da/strings.xml
@@ -20,6 +20,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kort er ikke tilladt MM#3"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc410-da/strings.xml b/core/res/res/values-mcc310-mnc410-da/strings.xml
index 3c5b9ee..3c9ab9c 100644
--- a/core/res/res/values-mcc310-mnc410-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc410-da/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="4477688981805467729">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc560-da/strings.xml b/core/res/res/values-mcc310-mnc560-da/strings.xml
index 95c214b..aac050c 100644
--- a/core/res/res/values-mcc310-mnc560-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc560-da/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="7030488670186895244">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc950-da/strings.xml b/core/res/res/values-mcc310-mnc950-da/strings.xml
index 97c801b..e8ab75c 100644
--- a/core/res/res/values-mcc310-mnc950-da/strings.xml
+++ b/core/res/res/values-mcc310-mnc950-da/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="8920048244573695129">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mcc311-mnc180-da/strings.xml b/core/res/res/values-mcc311-mnc180-da/strings.xml
index 5bcc43d..624a1c03 100644
--- a/core/res/res/values-mcc311-mnc180-da/strings.xml
+++ b/core/res/res/values-mcc311-mnc180-da/strings.xml
@@ -20,7 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kortet er ikke aktiveret MM#2"</string>
+    <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kortet er ikke provisioneret MM#2"</string>
     <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kort er ikke tilladt MM#3"</string>
     <string name="mmcc_illegal_me" msgid="5766888847785331904">"Telefonen har ikke adgangstilladelse MM#6"</string>
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 7144e4d..d30c8f2 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Овозможува апликацијата да прима и да обработува SMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"прими текстуални пораки (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Овозможува апликацијата да прима и да обработува MMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Проследување пораки за мобилен пренос"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дозволува апликацијата да се врзе со модулот за мобилен пренос за да проследува пораки за мобилен пренос штом ќе се примат. Предупредувањата за мобилно емитување се доставуваат на некои локации за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"прочитај пораки за мобилно емитување"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Овозможува апликациите да ги читаат пораките за мобилно емитување што ги прима вашиот уред. Предупредувањата за мобилно емитување се доставуваат на некои локации, за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читај претплатени навестувања на содржина"</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Отпечатокот е проверен"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Лицето е проверено"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Лицето е проверено, притиснете го копчето „Потврди“"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардвер за отпечаток од прст не е достапен."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатокот не може да се складира. Отстранете го постоечкиот отпечаток."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хардверот за отпечатоци не е достапен."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Отпечатокот не може да се складира. Отстранете некој од постојните отпечатоци."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцијата со отпечаток од прст се откажа."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцијата со отпечаток се откажа."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Корисникот ја откажа потврдата со отпечаток."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Премногу обиди. Обидете се повторно подоцна."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Премногу обиди. Сензорот за отпечатоци е оневозможен."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Дозволува апликацијата да чита и пишува конфигурација Не вознемирувај."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"започнете со користење на дозволата за приказ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Дозволува сопственикот да почне со користење на дозволата за апликација. Не треба да се користи за стандардни апликации."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"цел на кратенката за пристапност"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Дозволува апликација да одреди цел на кратенката за пристапност."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Постави правила за лозинката"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролирај ги должината и знаците што се дозволени за лозинки и PIN-броеви за отклучување екран."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Следи ги обидите за отклучување на екранот"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 479bb3a..5a604fb 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ജെസ്‌റ്ററുകൾ നിർവഹിക്കുക"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്‌റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ഫിംഗർപ്രിന്റ് ജെസ്‌റ്ററുകൾ"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ഉപകരണത്തിന്റെ വിരലടയാള സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്‌ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"വാചക സന്ദേശം നേടുക (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്‌ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ബ്രോഡ്‌കാസ്‌റ്റ് സന്ദേശങ്ങൾ കൈമാറുക"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"സ്വീകരിക്കുന്ന മുറയ്ക്ക് ബ്രോഡ്‌കാസ്‌റ്റ് സന്ദേശങ്ങൾ കൈമാറുന്നതിന് സെൽ ബ്രോഡ്‌കാസ്‌റ്റ് മോഡ്യൂളിലേക്ക് ബൈൻഡ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെ കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകുന്നതിന് ചില ലൊക്കേഷനുകളിൽ സെൽ ബ്രോഡ്‌കാസ്‌റ്റ് അലേർട്ടുകൾ ഡെലിവറി ചെയ്യപ്പെടുന്നു. ഒരു അടിയന്തര സെൽ ബ്രോഡ്‌കാസ്റ്റ് ലഭിക്കുമ്പോൾ ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെയോ പ്രവർത്തനത്തെയോ തടസപ്പെടുത്താനിടയുണ്ട്."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യുക"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭിച്ച സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെക്കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകാനായി ചില ലൊക്കേഷനുകളിൽ നൽകപ്പെടുന്നവയാണ് സെൽ പ്രക്ഷേപണ അലേർട്ടുകൾ. ഒരു അടിയന്തര സെൽ പ്രക്ഷേപണം ലഭിക്കുമ്പോൾ, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനമോ പ്രവർത്തനമോ തടസ്സപ്പെടുത്താനിടയുണ്ട്."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"സബ്‌സ്ക്രൈബ് ചെയ്‌ത ഫീഡുകൾ വായിക്കുക"</string>
@@ -517,9 +515,9 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ബയോമെട്രിക് ഹാർ‌ഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"പരിശോധിച്ചുറപ്പിക്കുന്നതിനായി, ബയോമെട്രിക് ഹാർഡ്‌വെയർ ഉപയോഗിക്കാൻ ആപ്പിനെ അനുവദിക്കുക"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ നിയന്ത്രിക്കുക"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ഉപയോഗിക്കാനായി വിരലടയാള ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ഉപയോഗിക്കാനായി ഫിംഗർപ്രിന്റ് ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"പ്രാമാണീകരണത്തിനായി വിരലടയാളം ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"പ്രാമാണീകരണത്തിനായി ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"നിങ്ങളുടെ സംഗീത ശേഖരം പരിഷ്‌കരിക്കുക"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"നിങ്ങളുടെ സംഗീത ശേഖരം പരിഷ്‌ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"നിങ്ങളുടെ വീഡിയോ ശേഖരം പരിഷ്‌കരിക്കുക"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"തിരിച്ചറിഞ്ഞില്ല"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"പരിശോധിച്ചുറപ്പിക്കൽ റദ്ദാക്കി"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"പിന്നോ പാറ്റേണോ പാസ്‌വേഡോ സജ്ജീകരിച്ചിട്ടില്ല"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"വിരലടയാളം ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"വിരലടയാളം പ്രോസസ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"വിരലടയാള സെൻസറിൽ ചെളിയുണ്ട്. അത് വൃത്തിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ഫിംഗർപ്രിന്റ് ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ഫിംഗർപ്രിന്റ് പ്രോസസ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെളിയുണ്ട്. അത് വൃത്തിയാക്കി വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"വിരൽ വളരെ വേഗത്തിൽ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"വിരൽ വളരെ പതുക്കെ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -545,19 +543,19 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു, സ്ഥിരീകരിക്കുക അമർത്തുക"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ഫിംഗർപ്രിന്റ് ഹാർഡ്‌വെയർ ലഭ്യമല്ല."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"വിരലടയാളം സംഭരിക്കാനാവില്ല. നിലവിലുള്ള വിരലടയാളം നീക്കംചെയ്യുക."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ഫിംഗർപ്രിന്റ് സംഭരിക്കാനാവില്ല. നിലവിലുള്ള ഫിംഗർപ്രിന്റ് നീക്കംചെയ്യുക."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ഫിംഗർപ്രിന്റ് നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ഉപയോക്താവ് റദ്ദാക്കിയ ഫിംഗർപ്രിന്‍റ് പ്രവർത്തനം."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"നിരവധി തവണ ശ്രമിച്ചതിനാൽ, വിരലടയാള സെൻസർ പ്രവർത്തനരഹിതമായി."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"നിരവധി തവണ ശ്രമിച്ചതിനാൽ, ഫിംഗർപ്രിന്റ് സെൻസർ പ്രവർത്തനരഹിതമായി."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"വീണ്ടും ശ്രമിക്കൂ."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"വിരലടയാളങ്ങൾ എൻറോൾ ചെയ്തിട്ടില്ല."</string>
-    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ഈ ഉപകരണത്തിൽ വിരലടയാള സെൻസറില്ല."</string>
+    <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ഈ ഉപകരണത്തിൽ ഫിംഗർപ്രിന്റ് സെൻസറില്ല."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"കൈവിരൽ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"വിരലടയാള ഐക്കൺ"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഹാർഡ്‌വെയർ മാനേജ് ചെയ്യുക"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"ഉപയോഗിക്കാനായി, മുഖത്തിന്റെ ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"മുഖം തിരിച്ചറിഞ്ഞുള്ള അൺലോക്ക് ഹാർഡ്‌വെയർ ഉപയോഗിക്കുക"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"\'ശല്യപ്പെടുത്തരുത്\' കോൺഫിഗറേഷൻ വായിക്കുന്നതിനും എഴുതുന്നതിനും ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"അനുമതി ഉപയോഗം കാണാൻ ആരംഭിക്കുക"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ഒരു ആപ്പിനുള്ള അനുമതി ഉപയോഗം ആരംഭിക്കാൻ ഹോൾഡറിനെ അനുവദിക്കുന്നു. സാധാരണ ആപ്പുകൾക്ക് ഒരിക്കലും ആവശ്യമില്ല."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ഉപയോഗസഹായി കുറുക്കുവഴിയുടെ ടാർഗറ്റ്"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ഉപയോഗസഹായി കുറുക്കുവഴിയുടെ ടാർഗറ്റ് നിർവ്വചിക്കാൻ ആപ്പിനെ അനുവദിക്കുക."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"പാസ്‌വേഡ് നിയമങ്ങൾ സജ്ജീകരിക്കുക"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"സ്‌ക്രീൻ ലോക്ക് പാസ്‌വേഡുകളിലും PIN-കളിലും അനുവദിച്ചിരിക്കുന്ന ദൈർഘ്യവും പ്രതീകങ്ങളും നിയന്ത്രിക്കുക."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"സ്‌ക്രീൻ അൺലോക്ക് ശ്രമങ്ങൾ നിരീക്ഷിക്കുക"</string>
@@ -1589,7 +1585,7 @@
     <string name="serial_number" msgid="758814067660862493">"സീരിയൽ നമ്പർ:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"വിരലടയാളങ്ങൾ:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 വിരലടയാളം:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA വിരലടയാളം:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA ഫിംഗർപ്രിന്റ്:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"എല്ലാം കാണുക"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"പ്രവർത്തനം തിരഞ്ഞെടുക്കുക"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"ഇവരുമായി പങ്കിടുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 1f29956..f4c6b60 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Апп нь SMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"текст мессеж(МMS) хүлээж авах"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Апп нь MMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг шилжүүлэх"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг хүлээн авах үед түүнийг шилжүүлэх зорилгоор аппад гар утсанд масс мессеж түгээх модультай холбогдохыг зөвшөөрөх Гар утсанд масс мессеж түгээх онцлогийн сэрэмжлүүлэг нь онцгой нөхцөл байдлын тухай танд анхааруулахын тулд зарим байршилд хүрдэг. Гар утсанд масс мессеж түгээх онцлогийн илгээх онцгой нөхцөл байдлын тухай мессежийг хүлээн авах үед хортой апп таны төхөөрөмжийн гүйцэтгэл эсвэл ажиллагаанд саад учруулж болзошгүй."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"үүрэн өргөн дамжууллын мессеж унших"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Апп нь таны төхөөрөмжийн хүлээн авсан үүрэн өргөн дамжуулах мессежийг унших боломжтой. Үүрэн өргөн дамжууллын мэдэгдэл нь яаралтай нөхцөл байдлыг анхааруулах зорилгоор зарим байршлуудад хүрдэг. Хортой апп нь яаралтай үүрэн өргөн дамжууллыг хүлээн авсан үед таны төхөөрөмжийн ажиллагаа болон чадамжид нөлөөлөх боломжтой."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"бүртгүүлсэн хангамжийг унших"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Аппад дэлгэцийн түгжээний боломжтой уртын хэмжээ болон төрлийг заадаг дэлгэцийн түгжээний төвөгтэй байдлын түвшнийг (өндөр, дундаж, бага эсвэл байхгүй) мэдэж авахыг зөвшөөрдөг. Түүнчлэн, апп хэрэглэгчдэд дэлгэцийн түгжээг тодорхой түвшинд шинэчлэхийг санал болгох боломжтой хэдий ч хэрэглэгч үүнийг чөлөөтэй үл хэрэгсэж, орхих боломжтой. Дэлгэцийн түгжээг ил бичвэрээр хадгалдаггүй тул энэ апп тодорхой нууц үгийг мэддэггүй болохыг анхаарна уу."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"биометрийн техник хангамжийг ашиглах"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Aппад биометрийн техник хангамжийг баталгаажуулалтад ашиглахыг зөвшөөрдөг"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"хурууны хээний програм хангамжийг удирдах"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загварыг нэмэх эсвэл усгтах үйлдлийг хийх зөвшөөрлийг програмд олгодог."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний програм хангамжийг ашиглах"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний апп хамгамжийг ашиглах зөвшөөрлийг аппд олгодог"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"хурууны хээний төхөөрөмжийг удирдах"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загвар нэмэх эсвэл устгах үйлдэл хийх зөвшөөрлийг аппд олгодог."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний төхөөрөмж ашиглах"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний төхөөрөмжийг ашиглах зөвшөөрлийг аппд олгодог"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"хөгжмийн цуглуулгаа тохируулах"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Таны хөгжмийн цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"видео цуглуулгаа тохируулах"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Тохируулсан пин, хээ эсвэл нууц үг алга"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Та цэвэрлэсний дараагаар дахин оролдоно уу."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Хурууны хээ мэдрэгч бохирдсон байна. Цэвэрлэсний дараа дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Хуруугаа хэт хурдан хөдөлгөсөн байна. Дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Хуруу хэт удаан хөдөлгөсөн байна. Дахин оролдоно уу."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -544,11 +542,11 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Хурууны хээг нотолсон"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Царайг баталгаажууллаа"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Царайг баталгаажууллаа. Баталгаажуулах товчлуурыг дарна уу"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хурууны хээний тоног төхөөрөмж бэлэн бус байна."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Хурууны хээний төхөөрөмж бэлэн бус байна."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Хурууны хээг хадгалах боломжгүй байна. Одоо байгаа хурууны хээг арилгана уу."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Хэрэглэгч хурууны хээн баталгаажуулалтыг цуцалсан байна."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Хэрэглэгч хурууны хээний баталгаажуулалтыг цуцалсан байна."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Хэтэрхий олон оролдлоо.  Түр хүлээгээд дахин оролдоно уу."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Хэт олон удаа оролдсон тул хурууны хээ мэдрэгчийг идэвхгүй болголоо."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Дахин оролдно уу."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Апп-д Бүү саад бол тохируулгыг уншиж, бичихийг зөвшөөрөх"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"зөвшөөрлийн ашиглалтыг харж эхлэх"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Эзэмшигчид аппын зөвшөөрлөө ашиглаж эхлэхийг зөвшөөрдөг. Энгийн аппуудад шаардлагагүй."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"хандалтын товчлолын зорилт"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Аппад хандалтын товчлолын зорилтыг тодорхойлохыг зөвшөөрдөг."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Нууц үгний дүрмийг тохируулах"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Дэлгэц түгжих нууц үг болон ПИН кодны урт болон нийт тэмдэгтийн уртыг хянах."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Дэлгэцийн түгжээг тайлах оролдлогыг хянах"</string>
@@ -1518,7 +1514,7 @@
     <string name="sync_do_nothing" msgid="3743764740430821845">"Одоо юу ч хийхгүй"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"Бүртгэл сонгох"</string>
     <string name="add_account_label" msgid="2935267344849993553">"Бүртгэл нэмэх"</string>
-    <string name="add_account_button_label" msgid="3611982894853435874">"Аккаунт нэмэх"</string>
+    <string name="add_account_button_label" msgid="3611982894853435874">"Бүртгэл нэмэх"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"Өсөх"</string>
     <string name="number_picker_decrement_button" msgid="476050778386779067">"Бууруулах"</string>
     <string name="number_picker_increment_scroll_mode" msgid="5259126567490114216">"<xliff:g id="VALUE">%s</xliff:g> хүрээд, хүлээнэ үү."</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Нэмэлт сонголтууд"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Дотоод хуваалцсан санах ой"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Дундын дотоод хадгалах сан"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD карт"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD карт"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB диск"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 5c6e358..4fb2347 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS मेसेज प्राप्त करण्याची आणि त्यावर प्रक्रिया करण्याची अ‍ॅप ला अनुमती देते. म्हणजेच अ‍ॅप आपल्या डीव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"मजकूर मेसेज मिळवा (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अ‍ॅप ला अनुमती देते. म्हणजेच अ‍ॅप आपल्या डिव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"सेल प्रसारण मेसेज फॉरवर्ड करा"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"सेल प्रसारण मेसेज मिळाल्यानंतर ते फॉरवर्ड करण्यासाठी अॅपला सेल प्रसारण मॉड्यूलमध्ये प्रतिबद्ध करण्याची अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थीतींची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरित केल्या जातात. दुर्भावनापूर्ण अॅप्स आणीबाणी सेल प्रसारण मिळवतात तेव्हा ती तुमच्या डिव्हाइसच्या परफॉर्मन्समध्ये किंवा कामामध्ये कदाचित व्यत्यय आणू शकतात."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारण मेसेज वाचा"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अ‍ॅप ला अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अ‍ॅप्स व्यत्यय आणू शकतात."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता घेतलेली फीड वाचा"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"व्यत्यय आणू नका कॉन्फिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"व्ह्यू परवानगी वापर सुरू करा"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"धारकास अ‍ॅपसाठी परवानगी वापरणे सुरू करण्याची अनुमती देते. सामान्य अ‍ॅप्ससाठी कधीही आवश्यकता नसते."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"अॅक्सेसिबिलिटी शॉर्टकट लक्ष्य"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"अ‍ॅपला अॅक्सेसिबिलिटी शॉर्टकट लक्ष्याबद्दल सांगण्यासाठी अनुमती द्या."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करा"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक पासवर्ड आणि पिन मध्ये अनुमती दिलेले लांबी आणि वर्ण नियंत्रित करा."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"स्क्रीन अनलॉक प्रयत्नांचे परीक्षण करा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index a7a4c99..4c811fd 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Membenarkan apl menerima dan memproses mesej SMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"terima mesej teks (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Membenarkan apl menerima dan memproses mesej MMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Kirim semula mesej siaran sel"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Membenarkan apl terikat pada modul siaran sel untuk mengirim semula mesej siaran sel apabila diterima. Makluman siaran sel dihantar di sesetengah lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"baca mesej siaran sel"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Membolehkan apl membaca mesej siaran sel yang diterima oleh peranti anda. Isyarat siaran sel dihantar di beberapa lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"baca suapan langganan"</string>
@@ -546,11 +544,11 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Wajah disahkan, sila tekan sahkan"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Perkakasan cap jari tidak tersedia."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Cap jari tidak dapat disimpan. Sila alih keluar cap jari sedia ada."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sudah tamat masa untuk cap jari. Cuba lagi"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Pengendalian cap jari dibatalkan."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Pengendalian cap jari dibatalkan oleh pengguna."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu banyak percubaan. Penderia cap jadi dilumpuhkan."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu banyak percubaan. Penderia cap jari dilumpuhkan."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Cuba lagi."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Tiada cap jari didaftarkan."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Peranti ini tiada penderia cap jari."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Membenarkan apl membaca dan menulis konfigurasi Jangan Ganggu."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"mulakan lihat penggunaan kebenaran"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Membenarkan pemegang memulakan penggunaan kebenaran untuk apl. Tidak sekali-kali diperlukan untuk apl biasa."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"sasaran pintasan kebolehaksesan"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Membenarkan apl mentakrifkan sasaran pintasan kebolehaksesan."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan  dan PIN kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Pantau percubaan buka kunci skrin"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index cbe8af4..38a33bf 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -324,7 +324,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"မျက်နှာပြင် ဇူးမ်အရွယ်နှင့် နေရာချထားခြင်းကို ထိန်းချုပ်ပါသည်။"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"လက်ဟန်များ အသုံးပြုပါ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"တို့ခြင်း၊ ပွတ်ဆွဲခြင်း၊ နှင့် အခြား လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်။"</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"လက်ဗွေရာများ"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"လက်ဗွေဟန်များ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"စက်ပစ္စည်း၏ လက်ဗွေအာရုံခံကိရိယာတွင် လုပ်ဆောင်ထားသည့် လက်ဟန်များကို မှတ်သားထားနိုင်သည်။"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"အပလီကေးရှင်းအား စာတိုများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"စာပို့ခြင်းအား လက်ခံရယူခြင်း (ရုပ်သံစာ)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"အပလီကေးရှင်းအား ရုပ်သံစာများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို ထပ်ဆင့်ပို့ခြင်း"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"စာတို ဖြန့်ဝေခြင်းစနစ် မော်ဂျူးကိုပေါင်းရန် အက်ပ်များအား ခွင့်ပြုသည်။ ၎င်းမှာ စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို လက်ခံရရှိသည့်အတိုင်း ထပ်ဆင့်ပို့ရန် ဖြစ်သည်။ အချို့တည်နေရာများတွင် သင့်အား အရေးပေါ်အခြေအနေများကို သတိပေးရန် စာတို ဖြန့်ဝေခြင်းစနစ်သုံး သတိပေးချက်များကို ပေးပို့သည်။ အရေးပေါ် စာတို ဖြန့်ဝေခြင်းကို ရရှိသည့်အခါ သံသယဖြစ်နိုင်ဖွယ်ရှိသည့် အက်ပ်များက သင့်စက်၏ စွမ်းဆောင်ရည်နှင့် အော်ပရေးရှင်းတို့ကို အနှောင့်အယှက်ပေးနိုင်သည်။"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"စာတိုများ ဖြန့်ဝေခြင်းစနစ်အား ဖတ်ခြင်း"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"အပလီကေးရှင်းကို သင်၏ စက်ပစ္စည်းမှ လက်ခံရရှိသော အများလွှင့်ထုတ်ချက်များကို ဖတ်ရန် ခွင့်ပြုသည်။  အများလွှင့်ထုတ်ချက်များသည် အရေးပေါ်အခြေအနေများကို သင့်အား သတိပေးရန် အချို့ နေရာများတွင် ပို့ပေးသည်။ အရေးပေါ်သတိပေးချက် ထုတ်လွှင့်ချက်ကို လက်ခံရရှိချိန်တွင်အန္တရာယ် ဖြစ်စေနိုင်သော အပလီကေးရှင်းများသည် သင့်စက်ပစ္စည်း၏ လုပ်ငန်းလည်ပတ်မှုနှင့် စွမ်းဆောင်မှုကို ဝင်စွက်ဖက်နိုင်သည်။"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"အမည်သွင်းထားသောဖိဖ့်များကို ဖတ်ခြင်း"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"ဖုန်းမျက်နှာပြင်လော့ခ်၏ ရှုပ်ထွေးမှုအဆင့် (မြင့်၊ အလယ်အလတ်၊ နိမ့် သို့မဟုတ် မရှိ) အား လေ့လာရန် အက်ပ်ကို ခွင့်ပြုသည်။ ၎င်းက သတ်မှတ်ထားနိုင်သော ဖုန်းမျက်နှာပြင်လော့ခ်၏ စာလုံးရေနှင့် အမျိုးအစားကို ညွှန်ပြပေးသည်။ အသုံးပြုသူများအနေနှင့် ဖုန်းမျက်နှာပြင်လော့ခ်ကို အတိုင်းအတာတစ်ခုအထိ အဆင့်မြှင့်ရန် အက်ပ်က အကြံပြုနိုင်သည်။ သို့သော်လည်း အသုံးပြုသူများက ၎င်းကို ဂရုပြုမနေဘဲ လွတ်လပ်စွာ ကြည့်ရှုနိုင်ပါသည်။ ဖုန်းမျက်နှာပြင်လော့ခ်ကို စာသားအတိုင်း သိမ်းမထားသဖြင့် အက်ပ်သည် စကားဝှက်အစစ်ကို မသိနိုင်ကြောင်း သတိပြုပါ။"</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ဇီဝဗေဒဆိုင်ရာ အချက်အလက်သုံး ကွန်ပျူတာဆိုင်ရာ စက်ပစ္စည်းကို အသုံးပြုရန်"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"အထောက်အထားစိစစ်ခြင်းအတွက် ဇီဝဗေဒဆိုင်ရာ သတင်းအချက်အလက်များသုံးသည့် ကွန်ပျူတာဆိုင်ရာ စက်ပစ္စည်းကို အသုံးပြုရန် အက်ပ်ကို ခွင့်ပြုသည်"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"လက်ဗွေရာပစ္စည်းကို စီမံမည်"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"အသုံးပြုရန်အတွက် လက်ဗွေရာပုံစံများကို ပေါင်းထည့်ရန် သို့မဟုတ် ဖျက်ရန်နည်းလမ်းများကို အပ်ဖ်အား အသုံးပြုခွင့်ပြုသည်။"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"လက်ဗွေရာပစ္စည်းကို အသုံးပြုမည်"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"စစ်မှန်ကြောင်းအထောက်အထားပြသခြင်းအတွက် လက်ဗွေရာပစ္စည်းကို အသုံးပြုရန် အပ်ဖ်အားခွင့်ပြုသည်။"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"လက်ဗွေစစ်ပစ္စည်းကို စီမံခြင်း"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"အသုံးပြုရန်အတွက် လက်ဗွေပုံစံများကို ပေါင်းထည့်ရန် သို့မဟုတ် ဖျက်ရန်နည်းလမ်းများကို အပ်က်အား သုံးခွင့်ပြုသည်။"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"လက်ဗွေ စက်ပစ္စည်းကို အသုံးပြုခြင်း"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"အထောက်အထားစိစစ်ရန်အတွက် အက်ပ်ကို လက်ဗွေစစ်ပစ္စည်း သုံးခွင့်ပြုသည်"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"သင့်တေးဂီတ စုစည်းမှုကို ပြုပြင်ခြင်း"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"အက်ပ်အား သင့်တေးဂီတစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"သင့်ဗီဒီယို စုစည်းမှုကို ပြုပြင်ခြင်း"</string>
@@ -534,8 +532,8 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"မသိ"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"အထောက်အထားစိစစ်ခြင်းကို ပယ်ဖျက်လိုက်သည်"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"ပင်နံပါတ်၊ လော့ခ်ပုံစံ သို့မဟုတ် စကားဝှက် သတ်မှတ်မထားပါ"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"လက်ဗွေရဦ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"လက်ဗွေရာယူခြင်း မဆောင်ရွက်နိုင်ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"လက်ဗွေ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"လက်ဗွေယူ၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"လက်ဗွေဖတ်ကိရိယာ ညစ်ပေနေသည်။ ကျေးဇူးပြု၍ သန့်ရှင်းလိုက်ပြီး ပြန်စမ်းကြည့်ပါ။"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"လက်ညှိုး အလွန်မြန်ဆန်စွာ ရွေ့ခဲ့သည်။ ထပ်မံ ကြိုးစားပါ။"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"လက်ညှိုးအလွန်နှေးကွေးစွာ ရွေ့ခဲ့သည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
@@ -544,20 +542,20 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"လက်ဗွေကို အထောက်အထား စိစစ်ပြီးပါပြီ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ၊ အတည်ပြုရန်ကို နှိပ်ပါ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"လက်ဗွေရာ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေရာ သိုလှောင်၍မရပါ။ ကျေးဇူးပြု၍ ရှိပြီးလက်ဗွေရာအား ဖယ်ရှားပါ။"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"လက်ဗွေရာ လုပ်ငန်း ဖျက်သိမ်းခဲ့၏။"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"လက်ဗွေ စက်ပစ္စည်းမရနိုင်ပါ။"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"လက်ဗွေ သိုလှောင်၍မရပါ။ လက်ရှိ လက်ဗွေကို ဖယ်ရှားပါ။"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေယူချိန်ကုန် သွားပါသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"လက်ဗွေယူခြင်း ပယ်ဖျက်လိုက်သည်။"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"လက်ဗွေဖြင့် အထောက်အထားစိစစ်ခြင်းကို အသုံးပြုသူက ပယ်ဖျက်ထားသည်။"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေဖတ်စနစ်ကို ပိတ်ထားပါသည်။"</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေအာရုံခံကိရိယာ ပိတ်ထားပါသည်။"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ပြန်ကြိုးစားပါ"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"မည်သည့် လက်ဗွေကိုမျှ ထည့်သွင်းမထားပါ။"</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ဤစက်တွင် လက်ဗွေအာရုံခံကိရိယာ မရှိပါ။"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"လက်ချောင်း <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"လက်ဗွေ အိုင်ကွန်"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"လက်ဗွေ သင်္ကေတ"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း စက်ပစ္စည်းကို စီမံခြင်း"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"အသုံးပြုရန်အတွက် မျက်နှာပုံစံထည့်ရန် (သို့) ဖျက်ရန်နည်းလမ်းကို အက်ပ်အား သုံးခွင့်ပြုသည်။"</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"မျက်နှာမှတ် သော့ဖွင့်ခြင်း စက်ပစ္စည်းကို သုံးပါ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"မနှောင့်ယှက်ရန် ချိန်ညှိမှုကို အပ်ဖ်များ ဖတ်ခြင်း ပြင်ခြင်းပြုလုပ်နိုင်ရန် ခွင့်ပြုမည်။"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"အစမြင်ကွင်း ခွင့်ပြုချက် အသုံးပြုမှု"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"အက်ပ်တစ်ခုအတွက် ခွင့်ပြုချက်စတင်အသုံးပြုမှုကို ကိုင်ဆောင်သူအား ခွင့်ပြုသည်။ ပုံမှန်အက်ပ်များအတွက် ဘယ်သောအခါမျှ မလိုအပ်ပါ။"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ် ပစ်မှတ်"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ် ပစ်မှတ်ကို အက်ပ်အား သတ်မှတ်ခွင့်ပြုသည်။"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"စကားဝှက်စည်းမျဥ်းကိုသတ်မှတ်ရန်"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"မျက်နှာပြင်သော့ခတ်သည့် စကားဝှက်များနှင့် PINများရှိ ခွင့်ပြုထားသည့် စာလုံးအရေအတွက်နှင့် အက္ခရာများအား ထိန်းချုပ်ရန်။"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"မျက်နှာပြင်လော့ခ်ဖွင့်ရန် ကြိုးပမ်းမှုများကို စောင့်ကြည့်ပါ"</string>
@@ -1165,7 +1161,7 @@
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"စနစ် ဆက်တင် ထဲမှာ ပုံသေကို ရှင်းလိုက်ပါ &gt; အက်ပ်များ &gt; ဒေါင်းလုဒ် လုပ်ပြီး။"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"လုပ်စရာ တစ်ခု ရွေးချယ်ပါ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ကိရိယာ အတွက် အက်ပ်တစ်ခု ရွေးပါ"</string>
-    <string name="noApplications" msgid="2991814273936504689">"ဘယ် အက်ပ်ကမှ ဒီ လုပ်ဆောင်ချက်ကို မလုပ်ကိုင်နိုင်ပါ။"</string>
+    <string name="noApplications" msgid="2991814273936504689">"မည်သည့်အက်ပ်ကမျှ ဤလုပ်ဆောင်ချက်ကို မလုပ်ကိုင်နိုင်ပါ။"</string>
     <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ရပ်သွားပါပြီ"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ရပ်တန့်သွားပါပြီ"</string>
     <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> သည်ထပ်တလဲလဲ ရပ်တန့်နေပါသည်"</string>
@@ -1588,8 +1584,8 @@
     <string name="expires_on" msgid="3676242949915959821">"သက်တမ်းကုန်ဆုံးရက်-"</string>
     <string name="serial_number" msgid="758814067660862493">"အစဉ်လိုက်နံပါတ်"</string>
     <string name="fingerprints" msgid="4516019619850763049">"လက်ပွေများ"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 လက်ပွေ"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 လက်ပွေ"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 လက်ဗွေ-"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 လက်ဗွေ-"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"အားလုံးကို ကြည့်ရန်"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"လုပ်ဆောင်ချက်ကို ရွေးရန်"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"...နှင့် မျှဝေရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 183e2e2..2d4a5f5 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lar appen motta og behandle tekstmeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"motta tekstmeldinger (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Lar appen motta og behandle multimediemeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Videresend kringkastede meldinger"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tillat at denne appen binder seg til modulen for kringkastede meldinger for å videresende kringkastede meldinger når de mottas. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lese kringkastede meldinger"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lese abonnement på nyhetskilder"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Lar appen lese og skrive konfigurasjon av Ikke forstyrr."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"start visning av bruk av tillatelser"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Lar innehaveren starte bruk av tillatelser for en app. Dette skal aldri være nødvendig for vanlige apper."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"mål for tilgjengelighetssnarvei"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tillat at en app definerer målet for tilgjengelighetssnarveien."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollerer tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Overvåk forsøk på å låse opp skjermen"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 4c4e1f0..dc44d2a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"इसाराहरू सम्बन्धी कार्य गर्नुहोस्"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ट्याप, स्वाइप गर्न, थिच्न र अन्य इसाराहरू सम्बन्धी कार्य गर्न सक्छ"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फिंगरप्रिन्टका इसाराहरू"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"यसले यन्त्रक‍ो फिङ्गरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"यसले यन्त्रक‍ो फिंगरप्रिन्टसम्बन्धी सेन्सरमा गरिएका इसाराहरूलाई खिच्‍न सक्छ।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"वस्तुस्थिति पट्टी हुन दिनुहोस्"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"अनुप्रयोगलाई SMS सन्देशहरू प्राप्त गर्न र प्रक्रिया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"पाठ सन्देश (MMS) प्राप्त गर्नुहोस्"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"अनुप्रयोगलाई MMS सन्देशहरू प्राप्त गर्न र प्रकृया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू फर्वार्ड गर्नुहोस्"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू प्राप्त हुनासाथै तिनीहरूलाई फर्वार्ड गर्नका लागि यसले अनुप्रयोगलाई मोबाइल प्रसारण मोड्युलमा जोडिने अनुमति दिन्छ। तपाईंलाई कतिपय स्थानमा आपत्कालीन अवस्थाका बारेमा जानकारी दिनका लागि मोबाइल प्रसारणसम्बन्धी अलर्टहरू पठाइन्छ। हानिकारक अनुप्रयोगहरूले आपत्कालीन मोबाइल प्रसारण प्राप्त हुँदा तपाईंको यन्त्रलाई कार्य सम्पादन गर्ने वा सञ्चालित हुने क्रममा हस्तक्षेप गर्न सक्छन्।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारित सन्देशहरू पढ्नुहोस्"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण सन्देशहरू अनुप्रयोगलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपतकालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब अनुप्रयोगहरूले एउटा आपतकालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्य बनाइका फिडहरू पढ्नुहोस्"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"यसले अनुप्रयोगलाई स्क्रिन लकको जटिलताको स्तर (उच्च, मध्यम, न्यून वा कुनै पनि होइन) थाहा पाउने अनुमति दिन्छ जसले स्क्रिन लकको लम्बाइको सम्भावित दायरा र त्यसको प्रकारलाई जनाउँछ। यसै गरी, यो अनुप्रयोगले प्रयोगकर्ताहरूलाई स्क्रिन लक अद्यावधिक गर्ने सुझाव पनि दिन सक्छ तर प्रयोगकर्ताहरू उक्त सुझावको बेवास्ता गरी बाहिर निस्कन सक्छन्। स्क्रिन लक सादा पाठको ढाँचामा भण्डारण नगरिने हुँदा यो अनुप्रयोगलाई वास्तविक पासवर्ड थाहा नहुने कुराको हेक्का राख्नुहोस्।"</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"बायोमेट्रिक हार्डवेयर प्रयोग गर्नुहोस्‌"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"अनुप्रयोगलाई प्रमाणीकरणका लागि बायोमेट्रिक हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"औठाछाप हार्डवेयर व्यवस्थापन गर्नुहोस्"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"अनुप्रयोगलाई प्रयोगको लागि औठाछाप टेम्प्लेट थप्न र मेटाउने तरिका आह्वान गर्न अनुमति दिन्छ।"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"औठाछाप हार्डवेयर प्रयोग गर्नुहोस्"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"अनुप्रयोगलाई प्रमाणीकरणको लागि औठाछाप हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"फिंगरप्रिन्ट हार्डवेयर व्यवस्थापन गर्नुहोस्"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"अनुप्रयोगलाई प्रयोगको लागि फिंगरप्रिन्ट टेम्प्लेट थप्न र मेटाउने तरिका आह्वान गर्न अनुमति दिन्छ।"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"फिंगरप्रिन्ट हार्डवेयर प्रयोग गर्नुहोस्"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"यो अनुप्रयोगलाई प्रमाणीकरणको लागि फिंगरप्रिन्ट हार्डवेयर प्रयोग गर्न अनुमति दिन्छ"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"आफ्नो सङ्गीतको सङ्ग्रह परिमार्जन गर्नुहोस्"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"यसले अनुप्रयोगलाई तपाईंको सङ्गीतको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"आफ्नो भिडियोको सङ्ग्रह परिमार्जन गर्नुहोस्"</string>
@@ -534,9 +532,9 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"पहिचान भएन"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"प्रमाणीकरण रद्द गरियो"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"कुनै पनि PIN, ढाँचा वा पासवर्ड सेट गरिएको छैन"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक औठाछाप पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"औठाछाप प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"औँठाछाप सेन्सर फोहोर छ। कृपया सफा गरेर फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फिंगरप्रिन्ट पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फिंगरप्रिन्ट प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फिंगरप्रिन्ट सेन्सर फोहोर छ। कृपया सफा गरेर फेरि प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"औंला धेरै छिटो चलाइयो। पुन: प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"औंला निकै सुस्त सारियो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -545,9 +543,9 @@
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"अनुहार प्रमाणीकरण गरियो"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"अनुहार प्रमाणीकरण गरियो, कृपया पुष्टि गर्नुहोस् थिच्नुहोस्"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"औँठाछाप हार्डवेयर उपलब्ध छैन।"</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"औँठाछाप भण्डारण गर्न सकिँदैन। कृपया अवस्थित औठाछाप हटाउनुहोस्।"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"औँठाछाप सञ्चालन रद्द गरियो।"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिन्ट भण्डारण गर्न सकिँदैन। कृपया अहिलेको फिंगरप्रिन्ट हटाउनुहोस्।"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिन्ट समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फिंगरप्रिन्ट सञ्चालन रद्द गरियो।"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"प्रयोगकर्ताले फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गर्नुभयो।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला"</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"अत्यन्त धेरै प्रयासहरू। फिंगरप्रिन्ट सेन्सरलाई असक्षम पारियो।"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"बाधा नपुर्याउँनुहोस् कन्फिगरेसन पढ्न र लेख्‍नको लागि अनुप्रयोगलाई अनुमति दिनुहोस्।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"हेर्ने अनुमतिको प्रयोग सुरु गर्नुहोस्"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"वाहकलाई कुनै अनुप्रयोगसम्बन्धी अनुमतिको प्रयोग सुरु गर्न दिन्छ। साधारण अनुप्रयोगहरूलाई कहिल्यै आवश्यक नपर्नु पर्ने हो।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"पहुँचसम्बन्धी सर्टकटको लक्ष्य"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"कुनै अनुप्रयोगलाई पहुँचसम्बन्धी सर्टकटको लक्ष्य परिभाषित गर्न दिन्छ।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"मनिटरको स्क्रिन अनलक गर्ने प्रयासहरू"</string>
@@ -1594,7 +1590,7 @@
     <string name="serial_number" msgid="758814067660862493">"क्रम संख्या:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"औँठाछापहरू:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-२५६ औंठाछाप:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 औंलाछाप:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 फिंगरप्रिन्ट:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"सबै हेर्नुहोस्"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"गतिविधि छनौट गर्नुहोस्"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"साझेदारी गर्नुहोस्..."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b3cc884..5c30c41 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Hiermee kan de app sms-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"tekstberichten (MMS) ontvangen"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Hiermee kan de app MMS-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Cell broadcast-berichten doorsturen"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Hiermee kan de app de module voor cell broadcasts binden om cell broadcast-berichten door te sturen als die worden ontvangen. Cell broadcast-waarschuwingen worden op bepaalde locaties verzonden om je te waarschuwen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren als een bericht met een noodmelding wordt ontvangen."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"infodienstberichten lezen"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Toestaan dat de app infodienstberichten leest die worden ontvangen op je apparaat. Infodienstberichten worden verzonden naar bepaalde locaties om u te waarschjeen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren wanneer een infodienstbericht wordt ontvangen."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"Geabonneerde feeds lezen"</string>
@@ -495,9 +493,9 @@
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9115646511110555589">"Hiermee kan de app pakketten ontvangen die via multicastadressen naar alle apparaten in een wifi-netwerk worden verzonden, niet alleen naar je Android TV-apparaat. Het stroomgebruik ligt hierbij hoger dan in de niet-multicastmodus."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Hiermee kan de app pakketten ontvangen die via multicastadressen naar alle apparaten in een wifi-netwerk worden verzonden, niet alleen naar je telefoon. Het stroomgebruik ligt hierbij hoger dan in de niet-multicastmodus."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth-instellingen openen"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Hiermee kan de app de lokale Bluetooth-tablet configureren en externe apparaten zoeken en koppelen."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Hiermee kan de app de lokale bluetooth-tablet configureren en externe apparaten zoeken en koppelen."</string>
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="3174333400857321862">"Hiermee kan de app Bluetooth op je Android TV-apparaat configureren en externe apparaten zoeken en koppelen."</string>
-    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Hiermee kan de app de lokale Bluetooth-telefoon configureren en externe apparaten zoeken en koppelen."</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Hiermee kan de app de lokale bluetooth-telefoon configureren en externe apparaten zoeken en koppelen."</string>
     <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX-verbinding maken en verbreken"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Hiermee kan de app bepalen of WiMAX is ingeschakeld en informatie bekijken over alle WiMAX-netwerken waarmee verbinding is gemaakt."</string>
     <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX-status wijzigen"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Hiermee kan de app configuratie voor Niet storen lezen en schrijven."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"rechtengebruik starten"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Hiermee kan de houder het rechtengebruik voor een app starten. Nooit vereist voor normale apps."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"doel van snelkoppeling voor toegankelijkheid"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Hiermee kan een app het doel van de snelkoppeling voor toegankelijkheid definiëren."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"De lengte en het aantal tekens beheren die zijn toegestaan in wachtwoorden en pincodes voor schermvergrendeling."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1229,10 +1225,10 @@
     <string name="sendText" msgid="5209874571959469142">"Een actie voor tekst selecteren"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Ringtonevolume"</string>
     <string name="volume_music" msgid="5421651157138628171">"Mediavolume"</string>
-    <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Afspelen via Bluetooth"</string>
+    <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Afspelen via bluetooth"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Stille ringtone ingesteld"</string>
     <string name="volume_call" msgid="3941680041282788711">"Volume inkomend gesprek"</string>
-    <string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume tijdens gesprek in Bluetooth-modus"</string>
+    <string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume tijdens gesprek in bluetooth-modus"</string>
     <string name="volume_alarm" msgid="1985191616042689100">"Wekkervolume"</string>
     <string name="volume_notification" msgid="2422265656744276715">"Meldingsvolume"</string>
     <string name="volume_unknown" msgid="1400219669770445902">"Volume"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index eb8f4c6..ac85a40 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -324,8 +324,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ଡିସପ୍ଲେର ଜୁମ୍‍ ସ୍ତର ଓ ପୋଜିସନିଙ୍ଗ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ଜେଶ୍ଚର୍‍ କରନ୍ତୁ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ଟାପ୍‍, ସ୍ୱାଇପ୍‍, ପିଞ୍ଚ ଓ ଅନ୍ୟାନ୍ୟ ଜେଶ୍ଚର୍‍ ସମ୍ପାଦନ କରିପାରିବ।"</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଜେଶ୍ଚର"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ଡିଭାଇସ୍‌ର ଆଙ୍ଗୁଠି ଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍‍ କ୍ୟାପଚର୍‍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ଟିପଚିହ୍ନ ଜେଶ୍ଚର"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"ଡିଭାଇସ୍‌ର ଟିପଚିହ୍ନ ସେନସର୍ ଉପରେ ଜେଶ୍ଚର୍‍ କ୍ୟାପଚର୍‍ କାର୍ଯ୍ୟ କରାଯାଇପାରିବ।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ଷ୍ଟାଟସ୍‌ ବାର୍‌କୁ ଅକ୍ଷମ କିମ୍ୱା ସଂଶୋଧନ କରନ୍ତୁ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ଆପ୍‍କୁ, ସ୍ଥିତି ବାର୍‍ ଅକ୍ଷମ କରିବାକୁ କିମ୍ବା ସିଷ୍ଟମ୍‍ ଆଇକନ୍‍ ଯୋଡ଼ିବା କିମ୍ବା ବାହାର କରିବାକୁ ଦେଇଥାଏ।"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ଷ୍ଟାଟସ୍‍ ବାର୍‍ ରହିବାକୁ ଦିଅନ୍ତୁ"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS ମେସେଜ୍‌ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍‍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ ହେଉଛି, ଆପଣଙ୍କ ଡିଭାଇସ୍‍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍‍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍‍ଟି ମନିଟର୍‍ କିମ୍ବା ଡିଲିଟ୍‍ କରିପାରେ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ଟେକ୍ସଟ୍‍ ମେସେଜ୍‍ (MMS) ପ୍ରାପ୍ତ କରନ୍ତୁ"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS ମେସେଜ୍‌ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍‍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ, ଆପଣଙ୍କ ଡିଭାଇସ୍‍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍‍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍‍ଟି ମନିଟର୍‍ କିମ୍ବା ଡିଲିଟ୍‍ କରିପାରେ।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ଫର୍‍ୱାର୍ଡ କରନ୍ତୁ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ପ୍ରାପ୍ତ ହେବା ପରେ ସେଗୁଡ଼ିକୁ ଫର୍‍ୱାର୍ଡ କରିବା ପାଇଁ ଆପ୍‍କୁ ସେଲ୍ ପ୍ରସାରଣ ମଡ୍ୟୁଲ୍ ସହିତ ସଂଯୁକ୍ତ କରିବାକୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ପରିସ୍ଥିତିରେ ଆପଣଙ୍କୁ ଚେତାବନୀ ଦେବା ପାଇଁ କିଛି ଲୋକେସନ୍‍‍ରେ ସେଲ୍ ପ୍ରସାରଣ ଆଲର୍ଟ ବିତରଣ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ପ୍ରସାରଣ ପ୍ରାପ୍ତ ହେବା ସମୟରେ କିଛି କ୍ଷତିକାରକ ଆପ୍ସ ହୁଏତ ଆପଣଙ୍କର ଡିଭାଇସ୍‍ର କାର୍ଯ୍ୟଦକ୍ଷତା କିମ୍ବା କାର୍ଯ୍ୟ ପ୍ରକ୍ରିୟାରେ ହସ୍ତକ୍ଷେପ କରିପାରେ।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢ଼ନ୍ତୁ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ରେ ପ୍ରାପ୍ତ ହୋଇଥିବା ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ଅବସ୍ଥା ବିଷୟରେ ଆପଣଙ୍କୁ ସତର୍କ କରାଇବାକୁ କିଛି ଲୋକେଶନ୍‍ରେ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ସତର୍କ ଡେଲିଭର୍ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ପ୍ରାପ୍ତ ହେବାପରେ ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ ଡିଭାଇସ୍‍ର କାର୍ଯ୍ୟକ୍ଷମତା କିମ୍ବା ସଞ୍ଚାଳନାରେ ବାଧା ପହଞ୍ଚାଇପାରନ୍ତି।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ସବସ୍କ୍ରାଇବ୍ ହୋଇଥିବା ଫୀଡ୍‌କୁ ପଢ଼ନ୍ତୁ"</string>
@@ -516,10 +514,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"ସ୍କ୍ରିନ୍ ଲକ୍‌ର ଜଟିଳତା ସ୍ତର (ଉଚ୍ଚ, ମଧ୍ୟମ, ନିମ୍ନ କିମ୍ବା କିଛିନୁହେଁ), ଜାଣିବାକୁ ଆପ୍‌କୁ ଅନୁମତି ଦିଅନ୍ତୁ, ଯାହା ସ୍କ୍ରିନ୍ ଲକ୍‌ର ସମ୍ଭାବ୍ୟ ପରିସୀମାର ଲମ୍ବ ଏବଂ ପ୍ରକାର ସୂଚୀତ କରେ। ଆପ୍ ଏହା ମଧ୍ୟ ଉପଯୋଗକର୍ତ୍ତାମାନଙ୍କୁ ପରାମର୍ଶ ଦେଇପାରେ ଯେ ସେମାନେ ସ୍କ୍ରିନ୍ ଲକ୍‌କୁ ଏକ ନିର୍ଦ୍ଧିଷ୍ଟ ସ୍ତର ପର୍ଯ୍ୟନ୍ତ ଅପ୍‌ଡେଟ୍ କରିପାରନ୍ତି, କିନ୍ତୁ ଉପଯୋଗକର୍ତ୍ତାମାନେ ନିଜ ଇଚ୍ଛାରେ ଏହାକୁ ଉପେକ୍ଷା ଏବଂ ନାଭିଗେଟ୍ କରିପାରିବେ। ଧ୍ୟାନ ଦିଅନ୍ତୁ ଯେ, ସ୍କ୍ରିନ୍ ଲକ୍ ସରଳ ଟେକ୍ସଟ୍‌ରେ ଷ୍ଟୋର୍ କରାଯାଇନଥାଏ ତେଣୁ ଆପ୍ ସଠିକ୍ ପାସ୍‌‍ୱର୍ଡ ଜାଣିପାରି ନଥାଏ।"</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"ବାୟୋମେଟ୍ରିକ୍‌ ହାର୍ଡୱେର୍‌ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"ସ୍ୱୀକୃତି ପାଇଁ ବାୟୋମେଟ୍ରିକ୍‌ ହାର୍ଡୱେର୍‌ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ପରିଚାଳନା କରନ୍ତୁ"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ବ୍ୟବହାର କରିବା ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ଯୋଡ଼ିବାକୁ ଓ ଡିଲିଟ୍‍ କରିବାକୁ ଆପକୁ ବିଧି ଆରମ୍ଭ କରିବାକୁ ଦେଇଥାଏ।"</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ସ୍ୱୀକୃତି ପାଇଁ ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ପରିଚାଳନା କରନ୍ତୁ"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ବ୍ୟବହାର କରିବା ପାଇଁ ଟିପଚିହ୍ନ ଟେମ୍ପ୍ଲେଟ୍ ଯୋଡ଼ିବାକୁ ଓ ଡିଲିଟ୍‍ କରିବାକୁ ଆପକୁ ପ୍ରକ୍ରିୟା ଆରମ୍ଭ କରିବାକୁ ଦେଇଥାଏ।"</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ପ୍ରମାଣିକରଣ ପାଇଁ ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦିଏ"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"ଆପଣଙ୍କ ସଙ୍ଗୀତ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"ଆପଣ ଆପଣଙ୍କ ସଙ୍ଗୀତ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"ଆପଣଙ୍କ ଭିଡିଓ ସଂଗ୍ରହ ସଂଶୋଧନ କରନ୍ତୁ"</string>
@@ -534,30 +532,30 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"ପ୍ରାମାଣିକତାକୁ ବାତିଲ୍ କରାଯାଇଛି"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"କୌଣସି ପିନ୍, ପେଟେର୍ନ ବା ପାସ୍‍ୱର୍ଡ ସେଟ୍ ନାହିଁ"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଂଶିକ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ଆଂଶିକ ଟିପଚିହ୍ନ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ଟିପଚିହ୍ନ ପ୍ରୋସେସ୍‍ କରାଯାଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"ଟିପଚିହ୍ନ ସେନ୍ସର୍‍ ମଇଳା ହୋଇଯାଇଛି। ଦୟାକରି ସଫା କରନ୍ତୁ ଓ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"ଆଙ୍ଗୁଠି ବହୁତ ଜୋର୍‌ରେ ଚଲାଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ଆଙ୍ଗୁଠି ଖୁବ୍‍ ଧୀରେ ନିଆଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରମାଣୀକୃତ ହେଲା"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"ଟିପଚିହ୍ନ ପ୍ରମାଣିତ ହେଲା"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି, ଦୟାକରି ସୁନିଶ୍ଚିତ ଦବାନ୍ତୁ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ହାର୍ଡୱେର୍‍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଷ୍ଟୋର୍‍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଆଙ୍ଗୁଠି ଚିହ୍ନକୁ ବାହାର କରିଦିଅନ୍ତୁ।"</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ଆଙ୍ଗୁଠି ଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣିଥରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ଆଙ୍ଗୁଠି ଚିହ୍ନ କାର୍ଯ୍ୟ କ୍ୟାନ୍ସଲ୍‍ କରାଗଲା।"</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ୟୁଜର୍‌ଙ୍କ ଦ୍ଵାରା ଆଙ୍ଗୁଠି ଚିହ୍ନ ନେବା କାମକୁ କ୍ୟାନ୍ସଲ୍ କରିଦିଆଯାଇଛି।"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍‍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ଟିପଚିହ୍ନ ଷ୍ଟୋର୍‍ କରାଯାଇପାରିବ ନାହିଁ। ଦୟାକରି ପୂର୍ବରୁ ଥିବା ଟିପଚିହ୍ନକୁ କାଢ଼ି ଦିଅନ୍ତୁ।"</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ଟିପଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରାଗଲା।"</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ଉପଯୋଗକର୍ତ୍ତା ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରିଛନ୍ତି।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ବହୁତ ପ୍ରୟାସ କରାଗଲା। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ବହୁତ ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଙ୍ଗୁଠି ଚିହ୍ନ ସେନ୍ସର୍‍ ଅକ୍ଷମ କରାଗଲା।"</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ବହୁଥର ପ୍ରୟାସ କରିଛନ୍ତି। ଟିପଚିହ୍ନ ସେନ୍ସର୍‍ ଅକ୍ଷମ କରାଯାଇଛି।"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"କୌଣସି ଆଙ୍ଗୁଠି ଚିହ୍ନ ପଞ୍ଜୀକୃତ ହୋଇନାହିଁ।"</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"ଏହି ଡିଭାଇସ୍‌ରେ ଟିପଚିହ୍ନ ସେନ୍‍ସର୍ ନାହିଁ।"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ଆଙ୍ଗୁଠି <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଇକନ୍"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"ଫେସ୍ ଅନ୍‌ଲକ୍ ହାର୍ଡୱେର୍ ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"ବ୍ୟବହାର ପାଇଁ ଆପ୍‍କୁ ଫେସିଆଲ୍‍ ଟେମ୍ପଲେଟ୍‍ ଯୋଡିବା ଓ ଡିଲିଟ୍‍ ର ପଦ୍ଧତି ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"ଫେସ୍ ଅନ୍‌ଲକ୍ ହାର୍ଡୱେର୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" କନଫିଗରେଶନ୍‍ ପଢ଼ିବା ତଥା ଲେଖିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ଅନୁମତି ବ୍ୟବହାର ଦେଖିବା ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ଏକ ଆପ୍ ପାଇଁ ଅନୁମତିର ବ୍ୟବହାର ଆରମ୍ଭ କରିବାକୁ ଧାରକକୁ ଅନୁମତି ଦେଇଥାଏ। ସାଧାରଣ ଆପ୍‌ଗୁଡ଼ିକ ପାଇଁ ଏହା ଆବଶ୍ୟକ ନୁହେଁ।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ଆକ୍ସେସିବିଲିଟୀ ସର୍ଟକଟ୍ ଟାର୍ଗେଟ୍"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ଆକ୍ସେସିବିଲିଟୀ ସର୍ଟକଟ୍ ଟାର୍ଗେଟ୍ ବ୍ୟାଖ୍ୟା କରିବା ପାଇଁ ଯେ କୌଣସି ଆପ୍‍କୁ ଅନୁମତି ଦିଏ।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ପାସ୍‌ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ଲକ୍‍ ସ୍କ୍ରୀନ୍‍ ପାସ୍‌ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ସ୍କ୍ରୀନ୍-ଅନଲକ୍ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରନ୍ତୁ"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"କ୍ରମିକ ସଂଖ୍ୟା:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ଆଙ୍ଗୁଠି ଚିହ୍ନ:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ଟିପଚିହ୍ନ:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"ସମସ୍ତ ଦେଖନ୍ତୁ"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ଗତିବିଧି ଚୟନ କରନ୍ତୁ"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"ଏହାଙ୍କ ସହ ସେୟାର୍‍ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index bc68885..177c7bc 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"ਐਪ ਨੂੰ SMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ਟੈਕਸਟ ਸੁਨੇਹੇ (MMS) ਪੜ੍ਹੋ"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ਐਪ ਨੂੰ MMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਨੂੰ ਅੱਗੇ ਭੇਜੋ"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"ਐਪ ਨੂੰ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਦੇ ਪ੍ਰਾਪਤ ਹੁੰਦੇ ਹੀ ਉਹਨਾਂ ਨੂੰ ਅੱਗੇ ਭੇਜਣ ਲਈ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਮਾਡਿਊਲ ਨਾਲ ਜੋੜਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਚੇਤਨਾਵਾਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਟਿਕਾਣਿਆਂ \'ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਭੈੜੀਆਂ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਕਾਰਗੁਜ਼ਾਰੀ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ਸੈਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹੇ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ਸਬਸਕ੍ਰਾਈਬ ਕੀਤੇ ਫੀਡਸ ਪੜ੍ਹੋ"</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ, ਕਿਰਪਾ ਕਰਕੇ \'ਪੁਸ਼ਟੀ ਕਰੋ\' ਦਬਾਓ"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।"</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰ"</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ।"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ਐਪ ਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨੂੰ ਪੜ੍ਹਨ ਅਤੇ ਲਿਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਦੇਖਣਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ਧਾਰਕ ਨੂੰ ਕਿਸੇ ਹੋਰ ਐਪ ਲਈ ਇਜਾਜ਼ਤ ਵਰਤੋਂ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਟੀਚਾ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ਕਿਸੇ ਐਪ ਨੂੰ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਟੀਚੇ ਨੂੰ ਪਰਿਭਾਸ਼ਿਤ ਕਰਨ ਦਿਓ।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ਪਾਸਵਰਡ ਨਿਯਮ ਸੈੱਟ ਕਰੋ"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਿੰਨ ਵਿੱਚ ਆਗਿਆ ਦਿੱਤੀ ਲੰਮਾਈ ਅਤੇ ਅੱਖਰਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ।"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 1dbe1c1..1f2430c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -234,7 +234,7 @@
     <string name="global_action_bug_report" msgid="7934010578922304799">"Zgłoszenie błędu"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Zakończ sesję"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Zrzut ekranu"</string>
-    <string name="bugreport_title" msgid="5981047024855257269">"Zgłoszenie błędu"</string>
+    <string name="bugreport_title" msgid="5981047024855257269">"Zgłoś błąd"</string>
     <string name="bugreport_message" msgid="398447048750350456">"Informacje o bieżącym stanie urządzenia zostaną zebrane i wysłane e-mailem. Przygotowanie zgłoszenia błędu do wysłania chwilę potrwa, więc zachowaj cierpliwość."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"Raport interaktywny"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"Używaj tej opcji w większości przypadków. Umożliwia śledzenie postępów raportu, podanie dodatkowych szczegółów problemu i wykonanie zrzutów ekranu. Raport może pomijać niektóre rzadko używane sekcje, których utworzenie zajmuje dużo czasu."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Pozwala aplikacji na odbieranie i przetwarzanie SMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"odbieranie wiadomości tekstowych (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Pozwala aplikacji na odbieranie i przetwarzanie MMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Przekaż komunikaty z sieci komórkowej"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Zezwala aplikacji powiązać się z modułem komunikatów z sieci komórkowej, aby przekazywać je w momencie, w którym są otrzymywane. W niektórych lokalizacjach komunikaty alarmowe z sieci komórkowej są dostarczane, aby ostrzec Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na działanie urządzenia lub zakłócać je po nadejściu komunikatu alarmowego z sieci komórkowej."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"odczyt komunikatów z sieci komórkowej"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Zezwala aplikacji na odczyt komunikatów z sieci komórkowej odebranych na urządzeniu. Komunikaty alarmowe z sieci komórkowej są dostarczane w niektórych lokalizacjach w celu ostrzeżenia Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na wydajność lub zakłócać działanie urządzenia po odebraniu komunikatu alarmowego z sieci komórkowej."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"czytanie subskrybowanych źródeł"</string>
@@ -552,7 +550,7 @@
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Twarz rozpoznana, kliknij Potwierdź"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Czytnik linii papilarnych nie jest dostępny."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Nie można zapisać odcisku palca. Usuń istniejący odcisk palca."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu odcisków palców. Spróbuj ponownie."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Odczyt odcisku palca został anulowany."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Odczyt odcisku palca został anulowany przez użytkownika."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zbyt wiele prób. Spróbuj ponownie później."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Pozwala aplikacji na odczyt i zmianę konfiguracji trybu Nie przeszkadzać."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"rozpocząć wyświetlanie użycia uprawnień"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Umożliwia rozpoczęcie korzystania z uprawnienia dotyczącego danej aplikacji jego posiadaczowi. Zwykłe aplikacje nie powinny potrzebować tego uprawnienia."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cel skrótu do ułatwień dostępu"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Pozwala aplikacji definiować cel skrótu do ułatwień dostępu."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorowanie prób odblokowania ekranu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c5bcb1d..05967af 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -237,8 +237,8 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não permite que você informe mais detalhes ou faça capturas de tela adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
-      <item quantity="other">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="one">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="other">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Som DESATIVADO"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que o app receba e processe mensagens SMS. Isso significa que o app pode monitorar ou excluir mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Encaminhar mensagens de transmissão celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensagens de difusão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds inscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permitir que o app leia e grave a configuração \"Não perturbe\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso da permissão para visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que o sistema inicie o uso de permissão para um app. Não deve ser necessário para apps comuns."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objetivo do atalho de acessibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que um app defina o objetivo do atalho de acessibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla o tamanho e os caracteres permitidos nos PINs e nas senhas do bloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorar tentativas de desbloqueio de tela"</string>
@@ -1373,10 +1369,10 @@
     <string name="usb_contaminant_detected_message" msgid="832337061059487250">"A porta USB é desativada automaticamente. Toque para saber mais."</string>
     <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"É seguro usar a porta USB"</string>
     <string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Não há mais líquidos ou detritos detectados no smartphone."</string>
-    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
-    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
-    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório do bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório de bug..."</string>
+    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório de bug?"</string>
+    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório de bug…"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
     <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
     <string name="select_input_method" msgid="4653387336791222978">"Selecione o método de entrada"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Armazenamento interno compartilhado"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Divisão interna de armazenamento"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"Drive USB"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 29ef549..400d576 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que a aplicação receba e processe mensagens SMS. Isto significa que a aplicação poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que a aplicação receba e processe mensagens MMS. Isto significa que a aplicação poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Encaminhar mensagens de difusão celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que a aplicação se vincule ao módulo de difusão celular para encaminhar mensagens de difusão celular à medida que são recebidas. Os alertas de difusão celular são fornecidos em algumas localizações para avisar sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma difusão celular de emergência."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensagens de transmissão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que a aplicação leia mensagens de transmissão celular recebidas pelo seu dispositivo. Os alertas de transmissão celular são fornecidos em algumas localizações para avisá-lo sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma transmissão celular de emergência."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds subscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite à aplicação ler e alterar a configuração de Não incomodar"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar utilização da autorização de visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que o titular inicie a utilização de autorizações para uma aplicação. Nunca deverá ser necessário para aplicações normais."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"alvo do atalho de acessibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite a uma aplicação definir o alvo do atalho de acessibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlar o comprimento e os carateres permitidos nos PINs e nas palavras-passe do bloqueio de ecrã."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorizar tentativas de desbloqueio do ecrã"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c5bcb1d..05967af 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -237,8 +237,8 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não permite que você informe mais detalhes ou faça capturas de tela adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
-      <item quantity="other">Capturas de tela para o relatório do bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="one">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
+      <item quantity="other">Capturas de tela para o relatório de bug serão feitas em <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Som DESATIVADO"</string>
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite que o app receba e processe mensagens SMS. Isso significa que o app pode monitorar ou excluir mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"receber mensagens de texto (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Encaminhar mensagens de transmissão celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensagens de difusão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds inscritos"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permitir que o app leia e grave a configuração \"Não perturbe\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"iniciar uso da permissão para visualização"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite que o sistema inicie o uso de permissão para um app. Não deve ser necessário para apps comuns."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objetivo do atalho de acessibilidade"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite que um app defina o objetivo do atalho de acessibilidade."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controla o tamanho e os caracteres permitidos nos PINs e nas senhas do bloqueio de tela."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorar tentativas de desbloqueio de tela"</string>
@@ -1373,10 +1369,10 @@
     <string name="usb_contaminant_detected_message" msgid="832337061059487250">"A porta USB é desativada automaticamente. Toque para saber mais."</string>
     <string name="usb_contaminant_not_detected_title" msgid="7708281124088684821">"É seguro usar a porta USB"</string>
     <string name="usb_contaminant_not_detected_message" msgid="2415791798244545292">"Não há mais líquidos ou detritos detectados no smartphone."</string>
-    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
-    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
-    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório do bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório de bug..."</string>
+    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório de bug?"</string>
+    <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório de bug…"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Seu administrador solicitou um relatório de bug para ajudar a resolver problemas deste dispositivo. É possível que apps e dados sejam compartilhados."</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
     <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
     <string name="select_input_method" msgid="4653387336791222978">"Selecione o método de entrada"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Armazenamento interno compartilhado"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Divisão interna de armazenamento"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"Drive USB"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 8ee45f9..27e6ec0 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Permite aplicației să primească și să proceseze mesaje SMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"primește mesaje text (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Redirecționează mesajele cu transmisie celulară"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Permite aplicației să se conecteze la modulul de transmisie celulară pentru a redirecționa mesajele cu transmisie celulară pe măsură ce le primește. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"citește mesajele cu transmisie celulară"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"citire feeduri abonat"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite aplicației să citească și să scrie configurația Nu deranja."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"porniți folosirea permisiunii de vizualizare"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Permite proprietarului să pornească folosirea permisiunii pentru o aplicație. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ținta comenzii rapide de accesibilitate"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Permite unei aplicații să definească ținta comenzii rapide de accesibilitate."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Să seteze reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Să monitorizeze încercările de deblocare a ecranului"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 655cf1b..6390b95 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Приложение сможет получать и обрабатывать SMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"Прием MMS-сообщений"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Приложение сможет получать и обрабатывать MMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Пересылка сообщений для оповещения населения"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Приложение сможет выполнить привязку к модулю оповещения населения, чтобы пересылать сообщения широковещательных SMS-служб сразу после их получения. В некоторых странах эти сообщения используются для информирования об экстренных ситуациях. Вредоносное ПО может помешать работе устройства, на которое поступают такие сообщения."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"Читать сообщения массовой рассылки"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"Просмотр фидов пользователя"</string>
@@ -386,7 +384,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Приложение сможет постоянно хранить свои компоненты в памяти. Это может уменьшить объем памяти, доступный другим приложениям, и замедлить работу устройства."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="47072473951071734">"Приложение сможет постоянно хранить свои компоненты в памяти. Это может уменьшить объем памяти, доступный другим приложениям, и замедлить работу устройства Android TV."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Приложение сможет постоянно хранить свои компоненты в памяти. Это может уменьшить объем памяти, доступный другим приложениям, и замедлить работу устройства."</string>
-    <string name="permlab_foregroundService" msgid="3310786367649133115">"запускать активные сервисы"</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"Запуск активных сервисов"</string>
     <string name="permdesc_foregroundService" msgid="6471634326171344622">"Разрешить приложению использовать активные сервисы."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"Вычисление объема памяти приложений"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Приложение сможет получать сведения о размере кода, данных и кеша."</string>
@@ -522,7 +520,7 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Приложение получит доступ к сведениям об уровне сложности блокировки экрана (высокий, средний, низкий или отсутствует), в том числе о типе блокировки и длине пароля. Кроме того, оно сможет предлагать пользователям повысить уровень сложности блокировки. Эти рекомендации необязательны. Обратите внимание, что пароль не хранится в виде открытого текста и недоступен приложению."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"Использование биометрического оборудования"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Приложение сможет использовать биометрическое оборудование для аутентификации"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управление сканером отпечатков"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управление сканером отпечатков пальцев"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Приложение сможет добавлять и удалять шаблоны отпечатков пальцев."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"Использование сканера отпечатков"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Приложение сможет использовать сканер отпечатков пальцев для аутентификации."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Открывает приложению доступ к настройкам режима \"Не беспокоить\" и позволяет изменять их."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"Просмотр данных об используемых разрешениях"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Приложение получит доступ к данным об используемых разрешениях. Это разрешение не требуется обычным приложениям."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Цель быстрого включения"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Приложение сможет определять цель быстрого включения."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Настройка правил для паролей"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролировать длину и символы при вводе пароля и PIN-кода."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Отслеживание попыток разблокировать экран"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 5fc6b53..fc69d0e 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS පණිවිඩ ලැබීමට සහ ක්‍රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. මෙහි තේරුම යෙදුමට ඔබගේ උපාංගයට ලැබෙන පණිවිඩ අධීක්ෂණය කිරීමට හැකිවීම වන අතර, ඒවා ඔබට නොපෙන්වා මකා දැමීමටද හැකි වීමයි."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"පෙළ පණිවුඩ ලබාගන්න (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS පණිවිඩ සොයා ලබාගැනීමට සහ ක්‍රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. යෙදුම නිරීක්ෂණය කරනු ලබන අතර ඔබට ලැබුන පණිවිඩ පෙන්වීමෙන් තොරවම මකා දැමිය හැකි බව මෙමඟින් අදහස් කරයි."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"සෙල් විකාශන පණිවිඩ යොමු කිරීම"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"සෙල් විකාශන පණිවිඩ ලැබුණු විට ඒවා යොමු කිරීම සඳහා සෙල් විකාශන මොඩියුලයට බැඳීමට යෙදුමට ඉඩ දෙයි. හදිසි අවස්ථා පිළිබඳව ඔබට අනතුරු ඇඟවීම සඳහා සෙල් විකාශන ඇඟවීම් සමහර ස්ථානවල ලබා දෙනු ලැබේ. හදිසි සෙල් විකාශනයක් ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම්වලින් ඔබගේ උපාංග කාර්ය සාධනයට හෝ මෙහෙයුමට බාධා සිදු විය හැකිය."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"සෙල් ප්‍රචාරණ පණිවිඩ කියවීම"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ඔබගේ උපාංගයට ලැබුණු සෙල් විකාශන පණිවිඩ කියවීමට යෙදුමට අවසර දෙන්න. ඔබට හදිසි අවස්ථාවන් පිළිබඳ අනතුරු ඇඟවීමට සෙල් විකාශන පණිවිඩ ඇතැම් ස්ථානවල සිට යවනු ලබයි. හදිසි සෙල් විකාශන ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම් මඟින් ඔබගේ උපාංගයට කාර්ය සාධනයට හෝ ක්‍රියකරණයට බාධා සිදුවිය හැක."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"දායක වූ සංග්‍රහ කියවීම"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"බාධා නොකරන්න වින්‍යාස කිරීම කියවීමට සහ ලිවීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"අවසර භාවිතය බැලීමට ආරම්භ කරන්න"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"තබා සිටින්නාට යෙදුමක් සඳහා අවසර භාවිතය ආරම්භ කිරීමට ඉඩ දෙයි. සාමාන්‍ය යෙදුම් සඳහා කිසි විටෙක අවශ්‍ය නොවිය යුතු ය."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ප්‍රවේශ්‍යතා කෙටිමං ඉලක්කය"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ප්‍රවේශ්‍යතා කෙටිමං ඉලක්කය නිර්වචනය කිරීමට යෙදුමකට ඉඩ දෙන්න."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"මුරපද නීති සකස් කිරීම"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"තිර අගුලු මුරපද සහ PIN තුළ ඉඩ දෙන දිග සහ අනුලකුණු පාලනය කිරීම."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"තිරය අගුළු ඇරීමේ උත්සාහයන් නිරීක්ෂණය කරන්න"</string>
@@ -1589,7 +1585,7 @@
     <string name="expires_on" msgid="3676242949915959821">"කල් ඉකුත් වන්නේ:"</string>
     <string name="serial_number" msgid="758814067660862493">"අනුක්‍රමාංකය:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"ඇඟිලි සලකුණු:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ඇඟිලිසලකුණ:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ඇඟිලි සලකුණ:"</string>
     <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ඇඟිලි සලකුණ:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"සියල්ල බලන්න"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ක්‍රියාකාරකම තෝරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ce17331..59e8b5e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -330,7 +330,7 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ovládajte umiestnenie a úroveň priblíženia obrazovky."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gestá"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Je možné použiť klepnutie, prejdenie, stiahnutie prstami a ďalšie gestá."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestá odtlačkom prstu"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestá odtlačkom prsta"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Dokáže zaznamenať gestá na senzore odtlačkov prstov zariadenia."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zakázanie alebo zmeny stavového riadka"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Umožňuje aplikácii prijímať a spracovávať správy SMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prijímať textové správy (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Umožňuje aplikácii prijímať a spracovávať správy MMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Preposielanie správ informačných služieb"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Umožňuje aplikácii spojiť sa s modulom správ informačných služieb s cieľom preposielať prichádzajúce správy informačných služieb. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"čítať správy informačných služieb"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Umožňuje aplikácii čítať správy informačných služieb prijaté vaším zariadením. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čítať odoberané informačné kanály"</string>
@@ -542,17 +540,17 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Nie je nastavený PIN, vzor ani heslo"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Podarilo sa rozpoznať iba časť odtlačku prsta. Skúste to znova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Odtlačok prsta sa nepodarilo spracovať. Skúste to znova."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Snímač odtlačkov je špinavý. Vyčistite ho a skúste to znova."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Snímač odtlačkov prstov je špinavý. Vyčistite ho a skúste to znova."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Pohli ste prstom príliš rýchlo. Skúste to znova."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Pohli ste prstom príliš pomaly. Skúste to znova."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Odtlačok bol overený"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Odtlačok prsta bol overený"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Tvár bola overená"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Tvár bola overená, stlačte tlačidlo potvrdenia"</string>
     <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardvér na snímanie odtlačku prsta nie je k dispozícii"</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Odtlačok prsta nie je možné uložiť. Odstráňte existujúci odtlačok."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Overenie odtlačku prsta zrušil používateľ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Umožňuje aplikácii čítať a zapisovať konfiguráciu režimu bez vyrušení."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"spustenie používania povolenia na zobrazenie"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Umožňuje držiteľovi spustiť používanie povolenia aplikáciou. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cieľ skratky dostupnosti"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Umožňuje aplikácii definovať cieľ skratky dostupnosti."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Nastavte dĺžku hesiel na odomknutie obrazovky aj kódov PIN a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Sledovanie pokusov o odomknutie obrazovky"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ec0863f..c49d5ff 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Aplikaciji omogoča prejemanje in obdelavo SMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prejemanje sporočil (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Aplikaciji omogoča prejemanje in obdelavo MMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Posredovanje sporočil oddaj v celici"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Aplikaciji omogoča povezovanje z modulom za oddaje v celici, da posreduje sporočila oddaj v celici, takoj ko jih prejme. Na nekaterih lokacijah so opozorila oddaj v celici dostavljena, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko prejme sporočilo oddaje v celici."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"branje sporočil oddaje v celici"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Omogoča aplikaciji branje sporočil oddaje v celici, ki jih prejme naprava. Opozorila oddaje v celici so dostavljena na nekaterih lokacijah, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko dobi sporočilo oddaje v celici."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"branje naročenih virov"</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Aplikaciji omogoča branje in pisanje konfiguracije načina »ne moti«."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"začetek uporabe dovoljenja za ogledovanje"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Imetniku omogoča začetek uporabe dovoljenj za aplikacijo. Nikoli ni potrebno za navadne aplikacije."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"cilj bližnjice funkcije za ljudi s posebnimi potrebami"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Aplikaciji dovoljuje, da določi cilj bližnjice funkcije za ljudi s posebnimi potrebami."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih in kodah PIN za odklepanje zaslona."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Nadzor nad poskusi odklepanja zaslona"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 95359cc..045c7d5 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Lejon aplikacionin të marrë dhe përpunojë mesazhe SMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"prano mesazhe në tekst (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Lejon aplikacionin të marrë dhe përpunojë mesazhe MMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Transmeto mesazhet e transmetimit celular"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Lejon që aplikacioni të lidhet me modulin e transmetimit celular për t\'i transferuar mesazhet e transmetimit celular menjëherë kur merren. Sinjalizimet e transmetimit celular dërgohen në disa vendndodhje për të të paralajmëruar për situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në cilësinë e funksionimit ose në veprimin e pajisjes sate kur merret një transmetim celular urgjent."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lexo mesazhet e transmetimit të qelizës"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Lejon aplikacionin të lexojë mesazhet e transmetimit të qelizës, të marra nga pajisja jote. Alarmet e transmetimit të qelizës dërgohen në disa vendndodhje për të të paralajmëruar në situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në veprimtarinë ose operacionin e pajisjes tënde kur merret një transmetim urgjent i qelizës."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"lexo informacione të abonuara"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Lejon aplikacionin të lexojë dhe shkruajë konfigurimin e \"Mos shqetëso\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"nis përdorimin e lejes për shikimin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Lejon që mbajtësi të nisë përdorimin e lejeve për një aplikacion. Nuk duhet të nevojitet asnjëherë për aplikacionet normale."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"objektivi i shkurtores së qasshmërisë"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Lejon që një aplikacion të përcaktojë objektivin e shkurtores së qasshmërisë."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Cakto rregullat e fjalëkalimit"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollo gjatësinë dhe karakteret e lejuara në fjalëkalimet dhe kodet PIN të kyçjes së ekranit."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitoro tentativat e shkyçjes së ekranit"</string>
@@ -1195,7 +1191,7 @@
     <string name="unsupported_display_size_show" msgid="7969129195360353041">"Shfaq gjithmonë"</string>
     <string name="unsupported_compile_sdk_message" msgid="4253168368781441759">"<xliff:g id="APP_NAME">%1$s</xliff:g> është ndërtuar për një version të papërputhshëm të sistemit operativ Android dhe mund të shfaqë sjellje të papritura. Mund të ofrohet një version i përditësuar i aplikacionit."</string>
     <string name="unsupported_compile_sdk_show" msgid="2681877855260970231">"Shfaq gjithnjë"</string>
-    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Kliko për përditësim"</string>
+    <string name="unsupported_compile_sdk_check_update" msgid="3312723623323216101">"Kontrollo për përditësim"</string>
     <string name="smv_application" msgid="3307209192155442829">"Aplikacioni <xliff:g id="APPLICATION">%1$s</xliff:g> (procesi <xliff:g id="PROCESS">%2$s</xliff:g>) ka shkelur politikën e tij të vetë-imponuar \"Modaliteti i ashpër\" (StrictMode)."</string>
     <string name="smv_process" msgid="5120397012047462446">"Procesi <xliff:g id="PROCESS">%1$s</xliff:g> ka shkelur politikën e tij të vetë-imponuar \"Modaliteti i rreptë\" (StrictMode)"</string>
     <string name="android_upgrading_title" product="default" msgid="7513829952443484438">"Telefoni po përditësohet…"</string>
@@ -1915,7 +1911,7 @@
     <string name="work_mode_off_message" msgid="5130856710614337649">"Aplikacionet e punës, njoftimet, të dhënat e tua dhe funksionet e tjera të profilit të punës do të aktivizohen"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivizo"</string>
     <string name="deprecated_target_sdk_message" msgid="1449696506742572767">"Ky aplikacion është ndërtuar për një version më të vjetër të Android dhe mund të mos funksionojë mirë. Provo të kontrollosh për përditësime ose kontakto me zhvilluesin."</string>
-    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Kliko për përditësim"</string>
+    <string name="deprecated_target_sdk_app_store" msgid="5032340500368495077">"Kontrollo për përditësim"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Ke mesazhe të reja"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Hap aplikacionin SMS për ta parë"</string>
     <string name="profile_encrypted_title" msgid="4260432497586829134">"Disa funksione mund të jenë të kufizuara"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 39ad5f4..0d8acc6 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -347,10 +347,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дозвољава апликацији да прима и обрађује SMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"пријем текстуалних порука (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Дозвољава апликацији да прима и обрађује MMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Прослеђивање порука за мобилне уређаје на локалитету"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дозвољава апликацији да се везује за модул порука за мобилне уређаје на локалитету да би прослеђивала поруке за мобилне уређаје на локалитету онако како су примљене. Обавештења порука за мобилне уређаје на локалитету се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају рад уређаја када се прими порука о хитном случају за мобилне уређаје на локалитету."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"читање порука инфо сервиса"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Омогућава апликацији да чита поруке инфо сервиса које уређај прима. Упозорења инфо сервиса се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају функционисање уређаја када се прими порука инфо сервиса о хитном случају."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читање пријављених фидова"</string>
@@ -662,8 +660,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Дозвољава апликацији да чита и уписује конфигурацију подешавања Не узнемиравај."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"почетак коришћења дозволе за преглед"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Дозвољава власнику да започне коришћење дозволе за апликацију. Никада не би требало да буде потребна за уобичајене апликације."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"циљ пречице за приступачност"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Дозвољава апликацији да дефинише циљ пречице за приступачност."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Контролише дужину и знакове дозвољене у лозинкама и PIN-овима за закључавање екрана."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Надгледајте покушаје откључавања екрана"</string>
@@ -1610,8 +1606,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Истиче:"</string>
     <string name="serial_number" msgid="758814067660862493">"Серијски број:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Дигитални отисци:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 дигитални отисак:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 дигитални отисак:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 отисак прста:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 отисак прста:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Прикажи све"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Избор активности"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Дели са"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 061d7b7..dba5ebb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillåter att appen tar emot och hanterar SMS. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ta emot textmeddelanden (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Tillåter att appen tar emot och hanterar MMS-meddelanden. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Vidarebefordra massutskick via sms"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Tillåter att appen binds till cellsändningsmodulen så att massutskick via sms kan vidarebefordras vid mottagandet. I vissa områden används massutskick via sms för att varna om nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktioner när ett massutskick via sms tas emot."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"läsa SMS-meddelanden"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Appen tillåts läsa SMS som skickas till din enhet. På vissa platser skickas SMS för att varna för nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktionalitet när du får ett meddelande om en nödsituation via SMS."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"läsa flöden som du prenumererar på"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ger appen läs- och skrivbehörighet till konfigurationen för Stör ej."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"börja visa behörighetsanvändningen"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Gör att innehavaren kan öppna behörighetsanvändning för en app. Ska inte behövas för vanliga appar."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"mål för Aktivera tillgänglighet snabbt"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Tillåter att en app kan definiera målet för Aktivera tillgänglighet snabbt."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Styr tillåten längd och tillåtna tecken i lösenord och pinkoder för skärmlåset."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Övervaka försök att låsa upp skärmen"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 16df4e3..89e3231 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Inaruhusu programu kupokea na kuchakata ujumbe wa SMS. Hii inamaanisha programu hii inaweza kuchunguza na kufuta ujumbe uliotumwa katika kifaa chako bila ya kukuonyesha."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"pokea ujumbe wa maandishi wa MMS"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Inaruhusu programu kupokea na kuchakata ujumbe medianwai (MMS). Hii inamaanisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwa kifaa chako bila ya kukuonyesha."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Sambaza ujumbe wa matangazo ya simu"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Huruhusu programu ipachikwe katika sehemu ya matangazo ya simu ili isambaze ujumbe wa matangazo ya simu unapopokewa. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendaji au shughuli ya kifaa chako matangazo ya simu ya dharura yanapopokewa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"soma mawasiliano ya matangazo ya simu"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Huruhusu programu kusoma mawasiliano ya matangazo ya simu yaliyoingia kwenye kifaa chako. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendajikazi au shughuli ya kifaa chako wakati matangazo ya simu ya dharura yameingia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"kusoma mipasho kutoka vyanzo unavyofuatilia"</string>
@@ -516,9 +514,9 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Huruhusu programu kupata maelezo kuhusu kiwango cha uchangamano wa kufunga skrini (juu, wastani, chini au hakuna), ambacho huashiria urefu unaowezekana na aina ya kufunga skrini. Programu pia inaweza kumpendekezea mtumiaji asasishe mbinu ya kufunga skrini iwe ya kiwango fulani lakini mtumiaji anaweza kuamua kupuuza na kuendelea. Kumbuka kuwa maelezo ya kufunga skrini hayahifadhiwi kama maandishi, hivyo programu haitambui nenosiri mahususi."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"tumia maunzi ya kibiolojia"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Huruhusu programu itumie maunzi ya kibiolojia katika uthibitishaji"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"dhibiti maunzi ya kitambulisho"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Huruhusu programu kuomba njia za kuongeza na kufuta violezo vya kitambulisho kwa matumizi."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"tumia maunzi ya kitambulisho"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"dhibiti maunzi ya alama ya kidole"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Huruhusu programu kuomba njia za kuongeza na kufuta violezo vya alama ya kidole kwa matumizi."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"tumia maunzi ya alama ya kidole"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Huruhusu programu kutumia maunzi ya kitambulisho kwa uthibitisho"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"kubadilisha mkusanyiko wako wa muziki"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Inaruhusu programu kubadilisha mkusanyiko wako wa muziki."</string>
@@ -534,7 +532,7 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Hayatambuliki"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Imeghairi uthibitishaji"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Hujaweka pin, mchoro au nenosiri"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Kitambuzi kimegundua sehemu ya kitambulisho. Tafadhali jaribu tena."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Kitambuzi kimegundua sehemu ya alama ya kidole. Tafadhali jaribu tena."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Imeshindwa kuchakata alama ya kidole. Tafadhali jaribu tena."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Kitambuzi alama ya kidole ni kichafu. Tafadhali kisafishe na ujaribu tena."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Ulisogeza kidole kwa kasi mno. Tafadhali jaribu tena."</string>
@@ -544,10 +542,10 @@
     <string name="fingerprint_authenticated" msgid="5309333983002526448">"Imethibitisha alama ya kidole"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Uso umethibitishwa"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Uso umethibitishwa, tafadhali bonyeza thibitisha"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maunzi ya kitambulisho hayapatikani."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Kitambulisho hakiwezi kuhifadhiwa. Tafadhali ondoa kitambulisho kilichopo."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Utendaji wa kitambulisho imeghairiwa."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Maunzi ya alama ya kidole hayapatikani."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Alama ya kidole haiwezi kuhifadhiwa. Tafadhali ondoa alama ya kidole iliyopo."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kuweka alama ya kidole umekwisha. Jaribu tena."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Mchakato wa alama ya kidole umeghairiwa."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Mtumiaji ameghairi uthibitishaji wa alama ya kidole."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Majaribio mengi mno. Jaribu tena baadaye."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Majaribio mengi mno. Kitambua alama ya kidole kimezimwa."</string>
@@ -557,7 +555,7 @@
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Kidole cha <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Aikoni ya kitambulisho"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Aikoni ya alama ya kidole"</string>
     <string name="permlab_manageFace" msgid="7262837876352591553">"dhibiti maunzi ya kufungua kwa uso"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"Huruhusu programu iombe njia za kuongeza na kufuta violezo vya uso vitakavyotumiwa."</string>
     <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"tumia maunzi ya kufungua kwa uso"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Inaruhusu programu kusoma na kuandika usanidi wa kipengee cha Usinisumbue."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"anzisha kipengele cha kuona matumizi ya ruhusa"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Huruhusu kishikiliaji kuanzisha matumizi ya ruhusa ya programu. Haipaswi kuhitajika kwa ajili ya programu za kawaida."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"kulenga njia ya mkato ya ufikivu"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Huruhusu programu kubainisha ulengaji wa njia ya mkato ya ufikivu."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Kuweka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Dhibiti urefu na maandishi yanayokubalika katika nenosiri la kufunga skrini na PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"Chaguo zaidi"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"Hifadhi ya ndani inayoshirikiwa"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"Hifadhi ya ndani ya pamoja"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"Kadi ya SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"Kadi ya SD iliyotengenezwa na <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"Hifadhi ya USB"</string>
@@ -1587,8 +1583,8 @@
     <string name="expires_on" msgid="3676242949915959821">"Inaisha muda mnamo:"</string>
     <string name="serial_number" msgid="758814067660862493">"Nambari ya ufuatiliaji:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"Alazama za Vidole:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"Alama ya  kidole ya SHA-256:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"Alama ya kidole ya  SHA-1:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"Kitambulisho dijitali cha SHA-256:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"Kitambulisho dijitali cha  SHA-1:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"Angalia zote"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"Chagua shughuli"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"Shiriki na"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 3b80a43..0ed1421 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS செய்திகளைப் பெற, செயற்படுத்தப் ஆப்ஸை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிப்பதற்கு அல்லது நீக்குவதற்கு ஆப்ஸால் முடியும் என்பதாகும்."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"உரைச் செய்திகளை (MMS) பெறுதல்"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS செய்திகளைப் பெற, செயற்படுத்தப் ஆப்ஸை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்கவோ, நீக்கவோ ஆப்ஸால் முடியும் என்பதாகும்."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"செல் பிராட்காஸ்ட் மெசேஜ்களை முன்னனுப்பு"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"செல் பிராட்காஸ்ட் மெசேஜ்களைப் பெறும்போதெல்லாம் அவற்றை முன்னனுப்பும் பொருட்டு, ஆப்ஸை செல் பிராட்காஸ்ட் மாடியூலோடு இணைக்கும். சில இடங்களில் அவசர சூழ்நிலைகளின் போது உங்களை எச்சரிக்க செல் பிராட்காஸ்ட் விழிப்பூட்டல்கள் அனுப்பப்படும். அவசரநிலை செல் பிராட்காஸ்ட்டைப் பெறும்போது, தீங்கிழைக்கும் ஆப்ஸ் உங்கள் சாதனத்தின் செயல்திறனுக்கோ செயல்பாட்டிற்கோ இடையூறு விளைவிக்கக்கூடும்."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"செல் அலைபரப்புச் செய்திகளைப் படித்தல்"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"உங்கள் சாதனத்தில் பெறப்படும் செல் அலைபரப்புச் செய்திகளைப் படிப்பதற்குப் ஆப்ஸை அனுமதிக்கிறது. அவசரநிலை சூழ்நிலைகளை உங்களுக்கு எச்சரிக்கைச் செய்வதற்கு சில இடங்களில் செல் அலைபரப்பு விழிப்பூட்டல்கள் வழங்கப்படும். அவசரநிலை மொபைல் அலைபரப்புப் பெறப்படும்போது உங்கள் சாதனத்தின் செயல்திறன் அல்லது செயல்பாட்டுடன் தீங்கிழைக்கும் ஆப்ஸ் அதைத் தடுக்கலாம்."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"குழுசேர்ந்த ஊட்டங்களைப் படித்தல்"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"தொந்தரவு செய்ய வேண்டாம் உள்ளமைவைப் படிக்கவும் எழுதவும், ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"அனுமதி உபயோகத்தை அணுகுதல்"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"ஆப்ஸிற்கான அனுமதி உபயோகத்தை ஹோல்டருக்கு வழங்கும். இயல்பான ஆப்ஸிற்கு இது எப்போதுமே தேவைப்படாது."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"அணுகலம்ச ஷார்ட்கட் இலக்கு"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"அணுகலம்ச ஷார்ட்கட் இலக்கை விளக்க ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"கடவுச்சொல் விதிகளை அமைக்கவும்"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"திரைப் பூட்டின் கடவுச்சொற்கள் மற்றும் பின்களில் அனுமதிக்கப்படும் நீளத்தையும் எழுத்துக்குறிகளையும் கட்டுப்படுத்தும்."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"திரையைத் திறப்பதற்கான முயற்சிகளைக் கண்காணி"</string>
@@ -1352,7 +1348,7 @@
     <string name="no_permissions" msgid="7283357728219338112">"அனுமதிகள் தேவையில்லை"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"இதனால் நீங்கள் கட்டணம் செலுத்த வேண்டியிருக்கலாம்"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"சரி"</string>
-    <string name="usb_charging_notification_title" msgid="1595122345358177163">"USB மூலமாக இந்தச் சாதனம் சார்ஜ் ஆகிறது"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"USBயில் சாதனம் சார்ஜ் ஆகிறது"</string>
     <string name="usb_supplying_notification_title" msgid="4631045789893086181">"USB மூலமாக இணைக்கப்பட்ட சாதனம் சார்ஜ் ஆகிறது"</string>
     <string name="usb_mtp_notification_title" msgid="4238227258391151029">"USB மூலமாக ஃபைல் பரிமாற்றம் ஆன் செய்யப்பட்டது"</string>
     <string name="usb_ptp_notification_title" msgid="5425857879922006878">"USB மூலமாக PTP பயன்முறை ஆன் செய்யப்பட்டது"</string>
@@ -1364,7 +1360,7 @@
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"அனலாக் ஆடியோ துணைக்கருவி கண்டறியப்பட்டது"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"இணைத்துள்ள சாதனமானது இந்த மொபைலுடன் இணங்கவில்லை. மேலும் அறிய, தட்டவும்."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB பிழைதிருத்தம் இணைக்கப்பட்டது"</string>
-    <string name="adb_active_notification_message" msgid="7463062450474107752">"USB பிழைதிருத்தத்தை ஆஃப் செய்ய, தட்டவும்"</string>
+    <string name="adb_active_notification_message" msgid="7463062450474107752">"USB பிழைதிருத்தத்தை ஆஃப் செய்ய தட்டவும்"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB பிழைதிருத்தத்தை முடக்க, தேர்ந்தெடுக்கவும்."</string>
     <string name="test_harness_mode_notification_title" msgid="2216359742631914387">"\'தன்னியக்க சோதனைப்\' பயன்முறை இயக்கப்பட்டது"</string>
     <string name="test_harness_mode_notification_message" msgid="1343197173054407119">"’தன்னியக்க சோதனைப்\' பயன்முறையை முடக்க ஆரம்பநிலைக்கு மீட்டமைக்கவும்."</string>
@@ -1588,8 +1584,8 @@
     <string name="expires_on" msgid="3676242949915959821">"காலாவதியாவது:"</string>
     <string name="serial_number" msgid="758814067660862493">"வரிசை எண்:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"கைரேகைகள்:"</string>
-    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 கைரேகை:"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 கைரேகை:"</string>
+    <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ஃபிங்கர்பிரிண்ட்:"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ஃபிங்கர்பிரிண்ட்:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"எல்லாம் காட்டு"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"செயல்பாட்டைத் தேர்வுசெய்க"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"இதனுடன் பகிர்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 37e0590..72b83c4 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. యాప్ మీ డివైజ్‌కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"వచన సందేశాలను (MMS) స్వీకరించడం"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. యాప్ మీ డివైజ్‌కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"సెల్ ప్రసార సందేశాలను ఫార్వర్డ్ చేయడం"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"సెల్ ప్రసార సందేశాలను అందుకుంటే, వాటిని ఫార్వర్డ్ చేసే విధంగా సెల్ ప్రసార మాడ్యూల్‌కు కట్టుబడి ఉండటానికి యాప్‌ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం అందుకున్నప్పుడు హానికరమైన యాప్‌లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"సెల్ ప్రసార సందేశాలను చదవడం"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి యాప్‌ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్‌లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"చందా చేయబడిన ఫీడ్‌లను చదవడం"</string>
@@ -517,9 +515,9 @@
     <string name="permlab_useBiometric" msgid="8837753668509919318">"బయోమెట్రిక్ హార్డ్‌వేర్‌ని ఉపయోగించు"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"ప్రమాణీకరణ కోసం బయోమెట్రిక్ హార్డ్‌వేర్‌ను ఉపయోగించడానికి యాప్‌ని అనుమతిస్తుంది"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"వేలిముద్ర హార్డ్‌వేర్‌ని నిర్వహించడానికి అనుమతి"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్‌లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్‌లను జోడించే, తొలగించే పద్ధతులను అమలు చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"వేలిముద్ర హార్డ్‌వేర్‌ని ఉపయోగించడానికి అనుమతి"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్‌వేర్‌ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్‌వేర్‌ను ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"మీ సంగీత సేకరణను సవరించండి"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"మీ సంగీత సేకరణని సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"మీ వీడియో సేకరణను సవరించండి"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"అంతరాయం కలిగించవద్దు ఎంపిక కాన్ఫిగరేషన్ చదవడానికి మరియు వ్రాయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"వీక్షణ అనుమతి వినియోగాన్ని ప్రారంభించండి"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"యాప్‌నకు అనుమతి వినియోగాన్ని ప్రారంభించడానికి హోల్డర్‌‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ ఇటువంటి అనుమతి అవసరం ఉండదు."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"యాక్సెసిబిలిటీ షార్ట్‌కట్ లక్ష్యం"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"యాక్సెసిబిలిటీ షార్ట్‌కట్ లక్ష్యాన్ని నిర్వచించడానికి యాప్‌ను అనుమతించండి."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"పాస్‌వర్డ్ నియమాలను సెట్ చేయండి"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"స్క్రీన్ లాక్ పాస్‌వర్డ్‌లు మరియు PINల్లో అనుమతించబడిన పొడవు మరియు అక్షరాలను నియంత్రిస్తుంది."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"స్క్రీన్ అన్‌లాక్ ప్రయత్నాలను పర్యవేక్షించండి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 482288e..caaa32d 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ SMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"รับข้อความ (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"ส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB)"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"อนุญาตให้แอปเชื่อมโยงกับโมดูลการส่งข้อมูลเตือนภัยทางมือถือ (CB) เพื่อส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ทันทีที่ได้รับ ระบบจะส่งการแจ้งเตือนจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในบางตำแหน่งเพื่อแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจรบกวนประสิทธิภาพหรือการทำงานของอุปกรณ์เมื่อได้รับการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในกรณีฉุกเฉิน"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"อนุญาตให้แอปอ่านข้อความจากสถานีมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางพื้นที่ โดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือนฉุกเฉิน"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"อ่านฟีดข้อมูลที่สมัครไว้"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"อนุญาตให้แอปอ่านและเขียนการกำหนดค่าโหมดห้ามรบกวน"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"เริ่มการใช้สิทธิ์การดู"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"อนุญาตให้เจ้าของเริ่มการใช้สิทธิ์ของแอป ไม่จำเป็นสำหรับแอปทั่วไป"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"เป้าหมายทางลัดการช่วยเหลือพิเศษ"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"อนุญาตให้แอปกำหนดเป้าหมายทางลัดการช่วยเหลือพิเศษ"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"ควบคุมความยาวและอักขระที่สามารถใช้ในรหัสผ่านของการล็อกหน้าจอและ PIN"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -1555,7 +1551,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ตัวเลือกเพิ่มเติม"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"ที่จัดเก็บข้อมูลที่ใช้ร่วมกันภายใน"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"พื้นที่จัดเก็บข้อมูลที่ใช้ร่วมกันภายใน"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"การ์ด SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"การ์ด SD ของ <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"ไดรฟ์ USB"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index f2db658..01cf28f 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng SMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"tumanggap ng mga text message (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng MMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Magpasa ng mga mensahe ng cell broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Nagbibigay-daan sa app na mag-bind sa module ng cell broadcast para makapagpasa ng mga mensahe ng cell broadcast pagkatanggap sa mga ito. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon para balaan ka tungkol sa mga emergency na sitwasyon. Posibleng makasagabal ang mga nakakahamak na app sa performance o pagpapatakbo ng iyong device kapag nakatanggap ito ng emergency na cell broadcast."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"basahin ang mga mensahe ng cell broadcast"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Binibigyang-daan ang app na magbasa ng mga mensahe ng cell broadcast na natanggap ng iyong device. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon upang balaan ka tungkol sa mga emergency na sitwasyon. Maaaring makaabala ang nakakahamak na apps sa performance o pagpapatakbo ng iyong device kapag nakatanggap ng emergency na cell broadcast."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"magbasa ng mga na-subscribe na feed"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Nagbibigay-daan sa app na basahin at isulat ang configuration ng Huwag Istorbohin."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"simulan ang paggamit sa pahintulot sa pagtingin"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Binibigyang-daan ang may hawak na simulan ang paggamit ng pahintulot para sa isang app. Hindi dapat kailanganin kailanman para sa mga normal na app."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"Target ng shortcut sa pagiging accessible"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Nagbibigay-daan sa isang app na tukuyin ang target ng shortcut sa pagiging accessible."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolin ang haba at ang mga character na pinapayagan sa mga password at PIN sa screen lock."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -1351,7 +1347,7 @@
     <string name="no_permissions" msgid="7283357728219338112">"Walang mga kinakailangang pahintulot"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"maaari itong magdulot ng gastos sa iyo"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="usb_charging_notification_title" msgid="1595122345358177163">"China-charge ang device na ito sa pamamagitan ng USB"</string>
+    <string name="usb_charging_notification_title" msgid="1595122345358177163">"China-charge ang device sa USB"</string>
     <string name="usb_supplying_notification_title" msgid="4631045789893086181">"China-charge ang nakakonektang device sa pamamagitan ng USB"</string>
     <string name="usb_mtp_notification_title" msgid="4238227258391151029">"Na-on ang paglipat ng USB file"</string>
     <string name="usb_ptp_notification_title" msgid="5425857879922006878">"Na-on ang PTP sa pamamagitan ng USB"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index cf3fbfc..d3e9d93 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Uygulamaya SMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"kısa mesajları (MMS) al"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Uygulamaya MMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Hücre yayını mesajlarını yönlendirme"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Uygulamanın hücre yayını mesajları geldiğinde bunları yönlendirmek için hücre yayını modülüne bağlanmasına izin verir. Hücre yayını uyarıları bazı konumlarda acil durumlar hakkında sizi uyarmak için kullanılır. Zararlı uygulamalar acil durum hücre yayını alındığında cihazınızın performansını ve çalışmasını olumsuz etkileyebilir."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"hücre yayını mesajlarını oku"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Uygulamaya, cihazınız tarafından alınan hücre yayını mesajlarını okuma izni verir. Hücre yayını uyarıları bazı yerlerde acil durumlar konusunda sizi uyarmak için gönderilir. Kötü amaçlı uygulamalar acil hücre yayını alındığında cihazınızın performansına ya da çalışmasına engel olabilir."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"abone olunan yayınları okuma"</string>
@@ -550,7 +548,7 @@
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Parmak izi işlemi iptal edildi."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Parmak izi işlemi kullanıcı tarafından iptal edildi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
-    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bıraıldı."</string>
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bırakıldı."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tekrar deneyin."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Parmak izi kaydedilmedi."</string>
     <string name="fingerprint_error_hw_not_present" msgid="409523969613176352">"Bu cihazda parmak izi sensörü yok."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Uygulamaya, Rahatsız Etmeyin yapılandırmasını okuma ve yazma izni verir."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"izin kullanımı görüntülemeye başlama"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"İzin sahibinin bir uygulama için izin kullanımı başlatmasına olanak tanır. Normal uygulamalar için hiçbir zaman kullanılmamalıdır."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"erişilebilirlik kısayolu hedefi"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Uygulamaların erişilebilirlik kısayolu hedefi tanımlamasına izin verir."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran kilidini açma şifrelerinde ve PIN\'lerde izin verilen uzunluğu ve karakterleri denetleyin."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekran kilidini açma denemelerini izle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 0ac716d..88350a2 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -350,10 +350,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Дозволяє програмі отримувати й обробляти SMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"отримувати текстові повідомлення (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Дозволяє програмі отримувати й обробляти MMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Переадресувати повідомлення Cell Broadcast"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Дозволяє додатку зв\'язуватися з модулем Cell Broadcast, щоб переадресувати відповідні вхідні повідомлення. У деяких місцеположеннях сповіщення Cell Broadcast надсилаються для попередження про надзвичайні ситуації. Після повідомлення Cell Broadcast шкідливі додатки можуть перешкоджати роботі вашого пристрою."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"читати широкомовні повідомлення мережі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Дозволяє програмі читати широкомовні повідомлення мережі, отримані пристроєм. Широкомовні сповіщення мережі надсилаються в деяких країнах для попередження про надзвичайні ситуації. Шкідливі програми можуть втручатися у швидкодію чи роботу пристрою під час отримання широкомовного повідомлення мережі про надзвичайну ситуацію."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читати підписані канали"</string>
@@ -522,10 +520,10 @@
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Дозволяє додатку визначати рівень складності способу блокування екрана (високий, середній, низький або нульовий). Враховуються кількість символів і тип блокування. Додаток також може пропонувати вибрати складніший тип блокування екрана, але це не обов’язково робити. Примітка: оскільки пароль зашифровано, додаток його не знає."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"використовувати біометричне апаратне забезпечення"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Додаток може використовувати біометричне апаратне забезпечення для автентифікації"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"керувати апаратним забезпеченням для цифрових відбитків"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Увімкнути в додатку функції для додавання й видалення шаблонів цифрових відбитків."</string>
-    <string name="permlab_useFingerprint" msgid="3150478619915124905">"використання сканера цифрових відбитків"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволити додатку використовувати апаратне забезпечення для автентифікації"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"керувати сканером відбитків пальців"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Увімкнути в додатку функції для додавання й видалення шаблонів відбитків пальців."</string>
+    <string name="permlab_useFingerprint" msgid="3150478619915124905">"використання сканера відбитків пальців"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволити додатку використовувати сканер відбитків пальців для автентифікації"</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"змінювати колекцію музики"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Додаток зможе змінювати вашу колекцію музики."</string>
     <string name="permlab_videoWrite" msgid="128769316366746446">"змінювати колекцію відео"</string>
@@ -540,20 +538,20 @@
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Не розпізнано"</string>
     <string name="biometric_error_canceled" msgid="349665227864885880">"Автентифікацію скасовано"</string>
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"Не вказано PIN-код, ключ або пароль"</string>
-    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Відбиток розпізнано частково. Повторіть спробу."</string>
-    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не вдалось обробити відбиток. Повторіть спробу."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчик відбитків забруднився. Очистьте його та повторіть спробу."</string>
+    <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Відбиток пальця розпізнано частково. Повторіть спробу."</string>
+    <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не вдалось обробити відбиток пальця. Повторіть спробу."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Датчик відбитків пальців забруднився. Очистьте його та повторіть спробу."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Ви забрали палець надто швидко. Повторіть спробу."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Ви провели пальцем надто повільно. Повторіть спробу."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Відбиток автентифіковано"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Відбиток пальця автентифіковано"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Обличчя автентифіковано"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Обличчя автентифіковано. Натисніть \"Підтвердити\""</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Апаратне забезпечення для сканування відбитка недоступне."</string>
-    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Не вдалося зберегти відбиток. Видаліть наявний відбиток."</string>
-    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка минув. Повторіть спробу."</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Дію з відбитком скасовано."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Сканер відбитків пальців недоступний."</string>
+    <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Не вдалося зберегти відбиток пальця. Видаліть наявний відбиток."</string>
+    <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка пальця минув. Повторіть спробу."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Дію з відбитком пальця скасовано."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Користувач скасував дію з відбитком пальця."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Забагато спроб. Спробуйте пізніше."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Забагато спроб. Сканер відбитків пальців вимкнено."</string>
@@ -665,8 +663,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Додаток зможе переглядати та змінювати конфігурацію режиму \"Не турбувати\"."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"перегляньте дані про використання дозволів"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Власник зможе використовувати дозволи для цього додатка. Цей дозвіл не потрібен для звичайних додатків."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"потрібні засоби спеціальних можливостей"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Дає додатку змогу визначати потрібні засоби спеціальних можливостей."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Укажіть максимальну довжину та кількість символів для паролів розблокування екрана та PIN-кодів."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Відстежувати спроби розблокування екрана"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 43ecaf6..e5015ea 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"‏ایپ کو SMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"‏متنی پیغامات (MMS) حاصل کریں"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"‏ایپ کو MMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"سیل کے نشریاتی پیغامات فارورڈ کریں"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"سیل کی نشریاتی پیغامات کے موصول ہوتے ہی فارورڈ کرنے کے لیے ایپ کو سیل کے نشریاتی ماڈیول میں پابندی لگانے کی اجازت دیں۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل براڈ کاسٹ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں مداخلت کر سکتی ہیں۔"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"سیل کے نشریاتی پیغامات پڑھیں"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ایپ کو آپ کے آلے کو موصولہ سیل کے نشریاتی پیغامات پڑھنے کی اجازت دیتا ہے۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل کا نشریہ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں خلل ڈال سکتی ہیں۔"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"سبسکرائب کردہ فیڈز پڑھیں"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ایپ کو ڈسٹرب نہ کریں کنفیگریشن لکھنے اور پڑھنے کے قابل کرتا ہے۔"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"اجازت کی استعمال کا ملاحظہ شروع کریں"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"حامل کو ایپ کی اجازت کے استعمال کو شروع کرنے کی اجازت دیتا ہے۔ عام ایپس کے لیے کبھی بھی درکار نہیں ہونا چاہیے۔"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"ایکسیسبیلٹی شارٹ کٹ ہدف"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"ایپ کو ایکسیسبیلٹی شارٹ کٹ ہدف کی وضاحت کرنے کے ليے اجازتیں۔"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"پاس ورڈ کے اصول سیٹ کریں"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"‏اسکرین لاک پاس ورڈز اور PINs میں اجازت یافتہ لمبائی اور حروف کو کنٹرول کریں۔"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"اسکرین غیر مقفل کرنے کی کوششیں مانیٹر کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 5ebda207..8899747 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ilovaga SMS xabarlarini qabul qilish va va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"MMS xabarlarni olish"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ilovaga MMS xabarlarini qabul qilish va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Aholini ogohlantirish xabarlarini uzatish"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Qabul qilingan aholini ogohlantirish xabarlarini shu holicha uzatish uchun ilovani aholini ogohlantirish moduliga bogʻlash imkonini beradi. Ilovaga ayrim mamlakatlarda aholini favqulodda vaziyatlarda ogohlantirish uchun yuboriladigan tarqatma xabarlarni oʻqish uchun ruxsat beradi. Zararli dasturlar bunday xabarlar kelayotgan qurilmaning ishlashiga xalaqit qilishi mumkin."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"uyali tarmoq operatori xabarlarini o‘qish"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ilovaga qurilmangiz tomonidan qabul qilingan uyali tarmoq operatori xabarlarini o‘qish uchun ruxsat beradi. Uyali tarmoq operatorining ogohlantiruvchi xabarlari ba’zi manzillarga favqulodda holatlar haqida ogohlantirish uchun jo‘natiladi. Zararli ilovalar uyali tarmoq orqali favqulodda xabar qabul qilinganda qurilmangizning ish faoliyati yoki amallariga xalaqit qilishi mumkin"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"obunalarni o‘qish"</string>
@@ -536,7 +534,7 @@
     <string name="biometric_error_device_not_secured" msgid="6583143098363528349">"PIN kod, grafik kalit yoki parol sozlanmagan"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmoq izi qisman aniqlandi. Qayta urinib ko‘ring."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmoq izi aniqlanmadi. Qaytadan urining."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Skanerni tozalab, keyin qaytadan urining."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Barmoq izi skanerini tozalab, keyin qaytadan urining."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Barmoq juda tez harakatlandi. Qaytadan urining."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Barmoq juda sekin harakatlandi. Qayta urinib ko‘ring."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"“Bezovta qilinmasin” rejimi sozlamalarini ko‘rish va o‘zgartirish."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"foydalaniladigan ruxsatlar axborotini ochish"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ilova foydalanadigan ruxsatlar axborotini ishga tushirishga ruxsat beradi. Oddiy ilovalar uchun talab qilinmaydi."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"tezkor yoqish maqsadi"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ilova tezkor yoqish maqsadini aniqlay oladi."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Parol qoidalarini o‘rnatish"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Ekran qulfi paroli va PIN kodlari uchun qo‘yiladigan talablarni (belgilar soni va uzunligi) nazorat qiladi."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Ekranni qulfdan chiqarishga urinishlarni nazorat qilish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index a34585b..fc8994e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"nhận tin nhắn văn bản (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Chuyển tiếp tin nhắn truyền phát trên di động"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Cho phép ứng dụng liên kết với mô-đun truyền phát trên di động để chuyển tiếp tin nhắn truyền phát trên di động ngay khi nhận được. Ở một số vị trí, thông báo truyền phát trên di động sẽ được gửi nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị khi nhận được tin nhắn truyền phát trên di động lúc khẩn cấp."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"đọc tin nhắn quảng bá"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Cho phép ứng dụng đọc tin nhắn quảng bá mà thiết bị của bạn nhận được. Tin nhắn quảng bá cảnh báo được gửi ở một số địa điểm nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể gây ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị của bạn khi nhận được tin nhắn quảng bá khẩn cấp."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"đọc nguồn cấp dữ liệu đã đăng ký"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Cho phép ứng dụng đọc và ghi cấu hình Không làm phiền."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"cấp quyền xem"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Cho phép chủ sở hữu cấp quyền cho một ứng dụng. Các ứng dụng thông thường sẽ không bao giờ cần quyền này."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"đích đến của phím tắt hỗ trợ tiếp cận"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Cho phép ứng dụng xác định đích đến của phím tắt hỗ trợ tiếp cận."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kiểm soát độ dài và ký tự được phép trong mật khẩu khóa màn hình và mã PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -737,7 +733,7 @@
   </string-array>
     <string name="phoneTypeCustom" msgid="1644738059053355820">"Tùy chỉnh"</string>
     <string name="phoneTypeHome" msgid="2570923463033985887">"Nhà riêng"</string>
-    <string name="phoneTypeMobile" msgid="6501463557754751037">"Di Động"</string>
+    <string name="phoneTypeMobile" msgid="6501463557754751037">"Di động"</string>
     <string name="phoneTypeWork" msgid="8863939667059911633">"Cơ quan"</string>
     <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Số fax cơ quan"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Số fax nhà riêng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 64e0a1b..56d8153 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允许该应用接收和处理短信。这就意味着,该应用可能会监视发送到您设备的短信,或删除发送到您设备的短信而不向您显示。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收讯息(彩信)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"允许该应用接收和处理彩信。这就意味着,该应用可能会监视发送到您设备的彩信,或删除发送到您设备的彩信而不向您显示。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"转发小区广播消息"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"允许应用绑定到小区广播模块,以便及时转发收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您的设备收到紧急小区广播时干扰设备的性能或操作。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"读取小区广播消息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允许应用读取您的设备收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您收到小区紧急广播时干扰您设备的性能或操作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"读取订阅的供稿"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"允许此应用读取和写入“勿扰”模式配置。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"授权使用“查看权限”"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"允许该应用开始查看应用的权限使用情况(普通应用绝不需要此权限)。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"无障碍功能快捷方式目标"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"允许应用定义无障碍功能快捷方式目标。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"控制锁屏密码和 PIN 码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"监控屏幕解锁尝试次数"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 67a7dbb..c8360aa 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理短訊。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收短訊 (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"允許應用程式接收和處理 MMS 訊息。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"轉寄區域廣播訊息"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"允許應用程式繫結至區域廣播模組,以在收到區域廣播訊息時轉寄訊息。在某些地點,系統會發出區域廣播通知,提示您有緊急狀況發生。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允許應用程式讀取您裝置接收的區域廣播訊息。某些地點會發出區域廣播警報,警告您發生緊急狀況。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的性能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"讀取訂閱的資訊提供"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"允許應用程式讀取和寫入「請勿騷擾」設定。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"開始查看權限使用情況"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"允許應用程式開始查看應用程式的權限使用情況 (一般應用程式並不需要)。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"無障礙功能捷徑目標位置"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"允許應用程式定義無障礙功能捷徑目標位置。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"控制螢幕鎖定密碼和 PIN 所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"監控螢幕解鎖嘗試次數"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 923a23f..23b68e1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"允許應用程式接收和處理簡訊。這項設定可讓應用程式監控傳送至你裝置的訊息,或在你閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"接收簡訊 (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"允許應用程式接收和處理多媒體訊息。這項設定可讓應用程式監控傳送至你裝置的訊息,或在你閱讀訊息前擅自刪除訊息。"</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"轉送區域廣播訊息"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"允許應用程式繫結至區域廣播模組,以便轉送收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允許應用程式讀取你裝置收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"讀取訂閱資訊提供"</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"允許應用程式讀取及寫入「零打擾」設定。"</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"啟動檢視權限用途"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"允許應用程式開始使用其他應用程式 (一般應用程式並不需要)。"</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"指定無障礙捷徑目標"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"允許應用程式定義指定的無障礙捷徑目標。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"管理螢幕鎖定密碼和 PIN 碼支援的字元和長度上限。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"監控螢幕解鎖嘗試次數"</string>
@@ -1588,7 +1584,7 @@
     <string name="serial_number" msgid="758814067660862493">"序號:"</string>
     <string name="fingerprints" msgid="4516019619850763049">"指紋"</string>
     <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 指紋"</string>
-    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指紋"</string>
+    <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 指紋:"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"全部顯示"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"選擇活動"</string>
     <string name="share_action_provider_share_with" msgid="5247684435979149216">"分享活動"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 04091ff..dac7c10 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -344,10 +344,8 @@
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-SMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"thola imiyalezo ebhaliwe (i-MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-MMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string>
-    <!-- no translation found for permlab_bindCellBroadcastService (4468585041824555604) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCellBroadcastService (9073440260695196089) -->
-    <skip />
+    <string name="permlab_bindCellBroadcastService" msgid="4468585041824555604">"Dlulisela imilayezo yokusakaza kweselula"</string>
+    <string name="permdesc_bindCellBroadcastService" msgid="9073440260695196089">"Ivumela uhlelo lokusebenza ukuthi luboshezelwe kumojuli yokusakaza kweselula ukuze kudluliselwe imilayezo yokusakaza yeselula njengoba itholwa. Izexwayiso zokusakaza kweselula zilethwa kwezinye izindawo ukuze zikuxwayise ngezimo zesimo esiphuthumayo. Izinhlelo zokusebenza ezinobungozi zingaphazamisa ngokusebenza noma ukusetshenziswa kwedivayisi yakho uma ukusakaza kweselula kwesimo esiphuthumayo kwamukelwa."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"funda imilayezo yokusakaza yeselula"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Ivumela uhlelo lokusebenza ukufunda imilayezo yokusakaza yeselula etholwe idivayisi yakho. Izaziso zokusakaza zeselula zilethwa kwezinye izindawo ukukuxwayisa ngezimo ezisheshayo. Izinhlelo zokusebenza ezingalungile zingaphazamisana nokusebenza noma umsebenzi wedivayisi yakho uma ukusakaza kweselula kwesimo esisheshayo kutholwa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"funda izifunzo ezikhokhelwayo"</string>
@@ -541,14 +539,14 @@
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Umnwe uhanjiswe kancane kakhulu. Sicela uzame futhi."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
-    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Isingxivizo somunwe sigunyaziwe"</string>
+    <string name="fingerprint_authenticated" msgid="5309333983002526448">"Izigxivizo zeminwe zigunyaziwe"</string>
     <string name="face_authenticated_no_confirmation_required" msgid="4018680978348659031">"Ubuso bufakazelwe ubuqiniso"</string>
     <string name="face_authenticated_confirmation_required" msgid="8778347003507633610">"Ukuqinisekiswa kobuso, sicela ucindezele okuthi qinisekisa"</string>
-    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Izingxenyekazi zekhompuyutha zezingxivizo zeminwe azitholakali."</string>
+    <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Izingxenyekazi zekhompuyutha zezigxivizo zeminwe azitholakali."</string>
     <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Izigxivizo zeminwe azikwazi ukugcinwa. Sicela ususe izigxivizo zeminwe ezikhona."</string>
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
-    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezingxivizo zeminwe kukhanseliwe."</string>
-    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Umsebenzi wesigxivizo somunwe sikhanselwe umsebenzisi."</string>
+    <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezigxivizo zeminwe kukhanseliwe."</string>
+    <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Umsebenzi wezigxivizo zomunwe ukhanselwe umsebenzisi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Imizamo eminingi kakhulu. Inzwa yezigxivizo zeminwe ikhutshaziwe."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zama futhi."</string>
@@ -659,8 +657,6 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ivumela izinhlelo zokusebenza ukufunda nokubhala ukulungiswa kokuthi Ungaphazamisi."</string>
     <string name="permlab_startViewPermissionUsage" msgid="5484728591597709944">"qala ukusetshenziswa kokubuka imvume"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="4808345878203594428">"Ivumela umphathi ukuthi aqale ukusetshenziswa kwemvume kohlelo lokusebenza. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
-    <string name="permlab_accessibilityShortcutTarget" msgid="1385930065395622809">"impokophelo yesinqamuleli sokufinyeleleka"</string>
-    <string name="permdesc_accessibilityShortcutTarget" msgid="562750894417800432">"Ivumela uhlelo lokusebenza ukuthi luchaze impokophelo yesinqamuleli sokufinyeleleka."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi wokukhiya isikrini nama-PIN."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Qapha imizamo yokuvula isikrini sakho"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 14f5d97..acaaeec 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3701,6 +3701,8 @@
             <flag name="flagRequestFingerprintGestures" value="0x00000200" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK}. -->
             <flag name="flagRequestShortcutWarningDialogSpokenFeedback" value="0x00000400" />
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_HANDLE_SHORTCUT}. -->
+            <flag name="flagHandleShortcut" value="0x00000800" />
         </attr>
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. This setting cannot be changed at runtime. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5605246..eaf93eb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -387,6 +387,12 @@
     </string-array>
 
     <!-- List of regexpressions describing the interface (if any) that represent tetherable
+         Wifi P2P interfaces.  If the device doesn't want to support tethering over Wifi P2p this
+         should be empty.  An example would be "p2p-p2p.*" -->
+    <string-array translatable="false" name="config_tether_wifi_p2p_regexs">
+    </string-array>
+
+    <!-- List of regexpressions describing the interface (if any) that represent tetherable
          WiMAX interfaces.  If the device doesn't want to support tethering over Wifi this
          should be empty.  An example would be "softap.*" -->
     <string-array translatable="false" name="config_tether_wimax_regexs">
@@ -442,7 +448,7 @@
     </string-array>
 
     <!-- Package name for the default CellBroadcastService module [DO NOT TRANSLATE] -->
-    <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastreceiver
+    <string name="cellbroadcast_default_package" translatable="false">com.android.cellbroadcastservice
     </string>
 
     <!-- If the mobile hotspot feature requires provisioning, a package name and class name
@@ -758,6 +764,9 @@
     <!-- Indicates that p2p MAC randomization is supported on this device -->
     <bool translatable="false" name="config_wifi_p2p_mac_randomization_supported">false</bool>
 
+    <!-- Indicates that AP mode MAC randomization is supported on this device -->
+    <bool translatable="false" name="config_wifi_ap_mac_randomization_supported">true</bool>
+
     <!-- flag for activating paranoid MAC randomization on a limited set of SSIDs -->
     <bool translatable="false" name="config_wifi_aggressive_randomization_ssid_whitelist_enabled">false</bool>
 
@@ -3543,6 +3552,9 @@
     <!-- emergency call number for the emergency affordance -->
     <string name="config_emergency_call_number" translatable="false">112</string>
 
+    <!-- Package name that provides Emergency Dialer -->
+    <string name="config_emergency_dialer_package">com.android.phone</string>
+
     <!-- Do not translate. Mcc codes whose existence trigger the presence of emergency
          affordances-->
     <integer-array name="config_emergency_mcc_codes" translatable="false">
@@ -4319,11 +4331,11 @@
 
     <!-- Trigger a warning for notifications with RemoteView objects that are larger in bytes than
     this value (default 1MB)-->
-    <integer name="config_notificationWarnRemoteViewSizeBytes">1000000</integer>
+    <integer name="config_notificationWarnRemoteViewSizeBytes">2000000</integer>
 
     <!-- Strip notification RemoteView objects that are larger in bytes than this value (also log)
     (default 2MB) -->
-    <integer name="config_notificationStripRemoteViewSizeBytes">2000000</integer>
+    <integer name="config_notificationStripRemoteViewSizeBytes">5000000</integer>
 
     <!-- Contains a blacklist of apps that should not get pre-installed carrier app permission
          grants, even if the UICC claims that the app should be privileged. See b/138150105 -->
@@ -4345,4 +4357,8 @@
          create additional screen real estate outside beyond the keyboard. Note that the user needs
          to have a confirmed way to dismiss the keyboard when desired. -->
     <bool name="config_automotiveHideNavBarForKeyboard">false</bool>
+
+    <!-- Whether or not to show the built-in charging animation when the device begins charging
+         wirelessly. -->
+    <bool name="config_showBuiltinWirelessChargingAnim">true</bool>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a01bbe3..9791241 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -41,6 +41,8 @@
     <dimen name="quick_qs_offset_height">48dp</dimen>
     <!-- Total height of QQS (quick_qs_offset_height + 128) -->
     <dimen name="quick_qs_total_height">176dp</dimen>
+    <!-- Total height of QQS with two rows to fit media player (quick_qs_offset_height + 176) -->
+    <dimen name="quick_qs_total_height_with_media">224dp</dimen>
     <!-- Height of the bottom navigation / system bar. -->
     <dimen name="navigation_bar_height">48dp</dimen>
     <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bf5f706..d39d507 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3440,6 +3440,15 @@
     <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. -->
     <string name="wifi_no_internet_detailed">Tap for options</string>
 
+    <!-- A notification is shown when the user connects to a mobile network without internet access. This is the notification's title. -->
+    <string name="mobile_no_internet">Mobile network has no internet access</string>
+
+    <!-- A notification is shown when the user connects to a non-mobile and non-wifi network without internet access. This is the notification's title. -->
+    <string name="other_networks_no_internet">Network has no internet access</string>
+
+    <!-- A notification is shown when connected network without internet due to private dns validation failed. This is the notification's message. [CHAR LIMIT=NONE] -->
+    <string name="private_dns_broken_detailed">Private DNS server cannot be accessed</string>
+
     <!-- A notification is shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the message of notification. [CHAR LIMIT=50] -->
     <string name="captive_portal_logged_in_detailed">Connected</string>
     <!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's title. [CHAR LIMIT=50] -->
@@ -5205,6 +5214,8 @@
     <string name="autofill_save_no">No thanks</string>
     <!-- Label for the autofill update button [CHAR LIMIT=NONE] -->
     <string name="autofill_update_yes">Update</string>
+    <!-- Label for the autofill continue button [CHAR LIMIT=NONE] -->
+    <string name="autofill_continue_yes">Continue</string>
 
     <!-- Label for the type of data being saved for autofill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
     <string name="autofill_save_type_password">password</string>
@@ -5212,6 +5223,12 @@
     <string name="autofill_save_type_address">address</string>
     <!-- Label for the type of data being saved for autofill when it represents a credit card [CHAR LIMIT=NONE] -->
     <string name="autofill_save_type_credit_card">credit card</string>
+    <!-- Label for the type of data being saved for autofill when it represents a debit card [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_debit_card">debit card</string>
+    <!-- Label for the type of data being saved for autofill when it represents a payment card [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_payment_card">payment card</string>
+    <!-- Label for the type of data being saved for autofill when it represents a card that does not a specified type or cannot identify what the type is for [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_generic_card">card</string>
     <!-- Label for the type of data being saved for autofill when it represents an username [CHAR LIMIT=NONE] -->
     <string name="autofill_save_type_username">username</string>
     <!-- Label for the type of data being saved for autofill when it represents an email address [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 42cd2cd..8d96c79 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -593,9 +593,12 @@
   <java-symbol type="string" name="menu_space_shortcut_label" />
   <java-symbol type="string" name="menu_shift_shortcut_label" />
   <java-symbol type="string" name="menu_sym_shortcut_label" />
+  <java-symbol type="string" name="mobile_no_internet" />
   <java-symbol type="string" name="notification_title" />
+  <java-symbol type="string" name="other_networks_no_internet" />
   <java-symbol type="string" name="permission_request_notification_with_subtitle" />
   <java-symbol type="string" name="prepend_shortcut_label" />
+  <java-symbol type="string" name="private_dns_broken_detailed" />
   <java-symbol type="string" name="paste_as_plain_text" />
   <java-symbol type="string" name="replace" />
   <java-symbol type="string" name="undo" />
@@ -1774,6 +1777,7 @@
   <java-symbol type="dimen" name="display_cutout_touchable_region_size" />
   <java-symbol type="dimen" name="quick_qs_offset_height" />
   <java-symbol type="dimen" name="quick_qs_total_height" />
+  <java-symbol type="dimen" name="quick_qs_total_height_with_media" />
   <java-symbol type="drawable" name="ic_jog_dial_sound_off" />
   <java-symbol type="drawable" name="ic_jog_dial_sound_on" />
   <java-symbol type="drawable" name="ic_jog_dial_unlock" />
@@ -1920,6 +1924,7 @@
   <java-symbol type="bool" name="config_tether_upstream_automatic" />
   <java-symbol type="array" name="config_tether_usb_regexs" />
   <java-symbol type="array" name="config_tether_wifi_regexs" />
+  <java-symbol type="array" name="config_tether_wifi_p2p_regexs" />
   <java-symbol type="array" name="config_usbHostBlacklist" />
   <java-symbol type="array" name="config_serialPorts" />
   <java-symbol type="array" name="radioAttributes" />
@@ -1970,6 +1975,7 @@
   <java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" />
   <java-symbol type="bool" name="config_wifi_connected_mac_randomization_supported" />
   <java-symbol type="bool" name="config_wifi_p2p_mac_randomization_supported" />
+  <java-symbol type="bool" name="config_wifi_ap_mac_randomization_supported" />
   <java-symbol type="bool" name="config_wifi_aggressive_randomization_ssid_whitelist_enabled" />
   <java-symbol type="bool" name="config_wifi_link_probing_supported" />
   <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
@@ -3163,6 +3169,7 @@
 
   <java-symbol type="string" name="global_action_emergency" />
   <java-symbol type="string" name="config_emergency_call_number" />
+  <java-symbol type="string" name="config_emergency_dialer_package" />
   <java-symbol type="array" name="config_emergency_mcc_codes" />
 
   <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
@@ -3352,6 +3359,7 @@
   <java-symbol type="string" name="autofill_update_title_with_2types" />
   <java-symbol type="string" name="autofill_update_title_with_3types" />
   <java-symbol type="string" name="autofill_update_yes" />
+  <java-symbol type="string" name="autofill_continue_yes" />
   <java-symbol type="string" name="autofill_save_accessibility_title " />
   <java-symbol type="string" name="autofill_save_title" />
   <java-symbol type="string" name="autofill_save_title_with_type" />
@@ -3362,6 +3370,9 @@
   <java-symbol type="string" name="autofill_save_type_password" />
   <java-symbol type="string" name="autofill_save_type_address" />
   <java-symbol type="string" name="autofill_save_type_credit_card" />
+  <java-symbol type="string" name="autofill_save_type_debit_card" />
+  <java-symbol type="string" name="autofill_save_type_payment_card" />
+  <java-symbol type="string" name="autofill_save_type_generic_card" />
   <java-symbol type="string" name="autofill_save_type_username" />
   <java-symbol type="string" name="autofill_save_type_email_address" />
   <java-symbol type="drawable" name="autofill_dataset_picker_background" />
@@ -3863,4 +3874,6 @@
 
   <java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" />
 
+  <java-symbol type="bool" name="config_showBuiltinWirelessChargingAnim" />
+
 </resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index f71c8b0..2d1c61c 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -90,7 +90,7 @@
     <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
 
     <!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
-    <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240" />
+    <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240|72438" />
 
     <!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
     <shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}|4665" />
diff --git a/core/tests/PlatformCompatFramework/Android.bp b/core/tests/PlatformCompatFramework/Android.bp
new file mode 100644
index 0000000..3380265
--- /dev/null
+++ b/core/tests/PlatformCompatFramework/Android.bp
@@ -0,0 +1,14 @@
+android_test {
+    name: "PlatformCompatFrameworkTests",
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: [
+        "junit",
+        "androidx.test.rules",
+    ],
+    platform_apis: true,
+}
diff --git a/core/tests/PlatformCompatFramework/AndroidManifest.xml b/core/tests/PlatformCompatFramework/AndroidManifest.xml
new file mode 100644
index 0000000..4a6383b
--- /dev/null
+++ b/core/tests/PlatformCompatFramework/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.internal.compat">
+    <application android:label="ChangeReporterTest">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.internal.compat"/>
+</manifest>
\ No newline at end of file
diff --git a/core/tests/PlatformCompatFramework/OWNERS b/core/tests/PlatformCompatFramework/OWNERS
new file mode 100644
index 0000000..2b7cdb0
--- /dev/null
+++ b/core/tests/PlatformCompatFramework/OWNERS
@@ -0,0 +1,7 @@
+# Use this reviewer by default.
+platform-compat-eng+reviews@google.com
+
+andreionea@google.com
+atrost@google.com
+mathewi@google.com
+satayev@google.com
diff --git a/core/tests/PlatformCompatFramework/src/com/android/internal/compat/ChangeReporterTest.java b/core/tests/PlatformCompatFramework/src/com/android/internal/compat/ChangeReporterTest.java
new file mode 100644
index 0000000..09bbe37
--- /dev/null
+++ b/core/tests/PlatformCompatFramework/src/com/android/internal/compat/ChangeReporterTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.internal.compat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class ChangeReporterTest {
+    @Test
+    public void testStatsLogOnce() {
+        ChangeReporter reporter = new ChangeReporter(0);
+        int myUid = 1022, otherUid = 1023;
+        long myChangeId = 500L, otherChangeId = 600L;
+        int myState = 1, otherState = 2;
+
+        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+        reporter.reportChange(myUid, myChangeId, myState);
+
+        // Same report will not be logged again.
+        assertFalse(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+        // Other reports will be logged.
+        assertTrue(reporter.shouldWriteToStatsLog(otherUid, myChangeId, myState));
+        assertTrue(reporter.shouldWriteToStatsLog(myUid, otherChangeId, myState));
+        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, otherState));
+    }
+
+    @Test
+    public void testStatsLogAfterReset() {
+        ChangeReporter reporter = new ChangeReporter(0);
+        int myUid = 1022;
+        long myChangeId = 500L;
+        int myState = 1;
+
+        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+        reporter.reportChange(myUid, myChangeId, myState);
+
+        // Same report will not be logged again.
+        assertFalse(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+        reporter.resetReportedChanges(myUid);
+
+        // Same report will be logged again after reset.
+        assertTrue(reporter.shouldWriteToStatsLog(myUid, myChangeId, myState));
+    }
+
+    @Test
+    public void testDebugLogOnce() {
+        ChangeReporter reporter = new ChangeReporter(0);
+        int myUid = 1022, otherUid = 1023;
+        long myChangeId = 500L, otherChangeId = 600L;
+        int myState = 1, otherState = 2;
+
+        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+        reporter.reportChange(myUid, myChangeId, myState);
+
+        // Same report will not be logged again.
+        assertFalse(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+        // Other reports will be logged.
+        assertTrue(reporter.shouldWriteToDebug(otherUid, myChangeId, myState));
+        assertTrue(reporter.shouldWriteToDebug(myUid, otherChangeId, myState));
+        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, otherState));
+    }
+
+    @Test
+    public void testDebugLogAfterReset() {
+        ChangeReporter reporter = new ChangeReporter(0);
+        int myUid = 1022;
+        long myChangeId = 500L;
+        int myState = 1;
+
+        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+        reporter.reportChange(myUid, myChangeId, myState);
+
+        // Same report will not be logged again.
+        assertFalse(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+        reporter.resetReportedChanges(myUid);
+
+        // Same report will be logged again after reset.
+        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+    }
+
+    @Test
+    public void testDebugLogWithLogAll() {
+        ChangeReporter reporter = new ChangeReporter(0);
+        int myUid = 1022;
+        long myChangeId = 500L;
+        int myState = 1;
+
+        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+        reporter.reportChange(myUid, myChangeId, myState);
+
+        reporter.startDebugLogAll();
+        // Same report will be logged again.
+        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+        assertTrue(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+
+        reporter.stopDebugLogAll();
+        assertFalse(reporter.shouldWriteToDebug(myUid, myChangeId, myState));
+    }
+}
diff --git a/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
new file mode 100644
index 0000000..1b5ad88
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/PhoneTimeSuggestionTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.app.timedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.TimestampedValue;
+
+import org.junit.Test;
+
+public class PhoneTimeSuggestionTest {
+    private static final int PHONE_ID = 99999;
+
+    @Test
+    public void testEquals() {
+        PhoneTimeSuggestion one =
+                new PhoneTimeSuggestion(PHONE_ID, new TimestampedValue<>(1111L, 2222L));
+        assertEquals(one, one);
+
+        PhoneTimeSuggestion two =
+                new PhoneTimeSuggestion(PHONE_ID, new TimestampedValue<>(1111L, 2222L));
+        assertEquals(one, two);
+        assertEquals(two, one);
+
+        PhoneTimeSuggestion three =
+                new PhoneTimeSuggestion(PHONE_ID + 1, new TimestampedValue<>(1111L, 2222L));
+        assertNotEquals(one, three);
+        assertNotEquals(three, one);
+
+        // DebugInfo must not be considered in equals().
+        one.addDebugInfo("Debug info 1");
+        two.addDebugInfo("Debug info 2");
+        assertEquals(one, two);
+    }
+
+    @Test
+    public void testParcelable() {
+        PhoneTimeSuggestion one =
+                new PhoneTimeSuggestion(PHONE_ID, new TimestampedValue<>(1111L, 2222L));
+        assertEquals(one, roundTripParcelable(one));
+
+        // DebugInfo should also be stored (but is not checked by equals()
+        one.addDebugInfo("This is debug info");
+        PhoneTimeSuggestion two = roundTripParcelable(one);
+        assertEquals(one.getDebugInfo(), two.getDebugInfo());
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T extends Parcelable> T roundTripParcelable(T one) {
+        Parcel parcel = Parcel.obtain();
+        parcel.writeTypedObject(one, 0);
+        parcel.setDataPosition(0);
+
+        T toReturn = (T) parcel.readTypedObject(PhoneTimeSuggestion.CREATOR);
+        parcel.recycle();
+        return toReturn;
+    }
+}
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
deleted file mode 100644
index f6527da..0000000
--- a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2012 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.content.pm;
-
-import android.net.Uri;
-import android.os.Parcel;
-import android.test.AndroidTestCase;
-
-import androidx.test.filters.LargeTest;
-
-/**
- * Tests the android.content.pm.VerificationParams class
- *
- * To test run:
- * ./development/testrunner/runtest.py frameworks-core -c android.content.pm.VerificationParamsTest
- */
-@LargeTest
-public class VerificationParamsTest extends AndroidTestCase {
-
-    private final static String VERIFICATION_URI_STRING = "http://verification.uri/path";
-    private final static String ORIGINATING_URI_STRING = "http://originating.uri/path";
-    private final static String REFERRER_STRING = "http://referrer.uri/path";
-    private final static int INSTALLER_UID = 42;
-
-    private final static Uri VERIFICATION_URI = Uri.parse(VERIFICATION_URI_STRING);
-    private final static Uri ORIGINATING_URI = Uri.parse(ORIGINATING_URI_STRING);
-    private final static Uri REFERRER = Uri.parse(REFERRER_STRING);
-
-    private final static int ORIGINATING_UID = 10042;
-
-    public void testParcel() throws Exception {
-        VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        Parcel parcel = Parcel.obtain();
-        expected.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-
-        VerificationParams actual = VerificationParams.CREATOR.createFromParcel(parcel);
-
-        assertEquals(VERIFICATION_URI, actual.getVerificationURI());
-
-        assertEquals(ORIGINATING_URI, actual.getOriginatingURI());
-
-        assertEquals(REFERRER, actual.getReferrer());
-
-        assertEquals(ORIGINATING_UID, actual.getOriginatingUid());
-    }
-
-    public void testEquals_Success() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-
-        assertEquals(params1, params2);
-    }
-
-    public void testEquals_VerificationUri_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_OriginatingUri_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_Referrer_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse("http://a.different.uri/"), ORIGINATING_UID);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_Originating_Uid_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), 12345);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testEquals_InstallerUid_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-        params2.setInstallerUid(INSTALLER_UID);
-
-        assertFalse(params1.equals(params2));
-    }
-
-    public void testHashCode_Success() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-
-        assertEquals(params1.hashCode(), params2.hashCode());
-    }
-
-    public void testHashCode_VerificationUri_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_OriginatingUri_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_Referrer_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
-                ORIGINATING_UID);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_Originating_Uid_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), 12345);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-
-    public void testHashCode_InstallerUid_Failure() throws Exception {
-        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
-                REFERRER, ORIGINATING_UID);
-
-        VerificationParams params2 = new VerificationParams(
-                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
-                Uri.parse(REFERRER_STRING), ORIGINATING_UID);
-        params2.setInstallerUid(INSTALLER_UID);
-
-        assertFalse(params1.hashCode() == params2.hashCode());
-    }
-}
diff --git a/core/tests/coretests/src/android/view/InsetsFlagsTest.java b/core/tests/coretests/src/android/view/InsetsFlagsTest.java
new file mode 100644
index 0000000..7d4445b
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsFlagsTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.view;
+
+
+import static android.view.InsetsFlags.getAppearance;
+import static android.view.View.NAVIGATION_BAR_TRANSLUCENT;
+import static android.view.View.NAVIGATION_BAR_TRANSPARENT;
+import static android.view.View.STATUS_BAR_TRANSLUCENT;
+import static android.view.View.STATUS_BAR_TRANSPARENT;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_TOP_BAR;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.WindowInsetsController.Appearance;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link InsetsFlags}.
+ *
+ * <p>Build/Install/Run:
+ *  atest FrameworksCoreTests:InsetsFlagsTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class InsetsFlagsTest {
+
+    @Test
+    public void testGetAppearance() {
+        assertContainsAppearance(APPEARANCE_LOW_PROFILE_BARS, SYSTEM_UI_FLAG_LOW_PROFILE);
+        assertContainsAppearance(APPEARANCE_LIGHT_TOP_BAR, SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+        assertContainsAppearance(APPEARANCE_LIGHT_SIDE_BARS, SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+        assertContainsAppearance(APPEARANCE_OPAQUE_TOP_BAR,
+                0xffffffff & ~(STATUS_BAR_TRANSLUCENT | STATUS_BAR_TRANSPARENT));
+        assertContainsAppearance(APPEARANCE_OPAQUE_SIDE_BARS,
+                0xffffffff & ~(NAVIGATION_BAR_TRANSLUCENT | NAVIGATION_BAR_TRANSPARENT));
+    }
+
+    void assertContainsAppearance(@Appearance int appearance, int systemUiVisibility) {
+        assertTrue((getAppearance(systemUiVisibility) & appearance) == appearance);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index cc6eeed..5ea91da 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -284,7 +284,7 @@
         waitForIdle();
         UsageStatsManager usm = activity.getUsageStatsManager();
         verify(sOverrides.resolverListController, times(1))
-                .sort(Mockito.any(List.class));
+                .topK(Mockito.any(List.class), Mockito.anyInt());
         assertThat(activity.getIsSelected(), is(false));
         sOverrides.onSafelyStartCallback = targetInfo -> {
             return true;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 453bddd..0fa29bf 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -38,6 +38,7 @@
 import android.widget.RelativeLayout;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.espresso.Espresso;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -82,6 +83,7 @@
                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
 
         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        Espresso.registerIdlingResources(activity.getLabelIdlingResource());
         waitForIdle();
 
         assertThat(activity.getAdapter().getCount(), is(2));
@@ -214,6 +216,7 @@
                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
 
         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        Espresso.registerIdlingResources(activity.getLabelIdlingResource());
         waitForIdle();
 
         // The other entry is filtered to the last used slot
@@ -251,6 +254,7 @@
                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
 
         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        Espresso.registerIdlingResources(activity.getLabelIdlingResource());
         waitForIdle();
 
         // The other entry is filtered to the other profile slot
@@ -296,6 +300,7 @@
                 .thenReturn(resolvedComponentInfos.get(1).getResolveInfoAt(0));
 
         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        Espresso.registerIdlingResources(activity.getLabelIdlingResource());
         waitForIdle();
 
         // The other entry is filtered to the other profile slot
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
index fcec00e..5ac1489 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.app;
 
+import static junit.framework.Assert.assertEquals;
+
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.mockito.Matchers.any;
@@ -41,6 +43,8 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -112,13 +116,41 @@
         when(mMockContext.getSystemService(Context.USAGE_STATS_SERVICE)).thenReturn(mUsm);
         mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
                 refererPackage, UserHandle.USER_CURRENT);
-        mController.sort(new ArrayList<ResolverActivity.ResolvedComponentInfo>());
+        mController.sort(new ArrayList<ResolvedComponentInfo>());
         long beforeReport = getCount(mUsm, packageName, action, annotation);
         mController.updateChooserCounts(packageName, UserHandle.USER_CURRENT, action);
         long afterReport = getCount(mUsm, packageName, action, annotation);
         assertThat(afterReport, is(beforeReport + 1l));
     }
 
+    @Test
+    public void topKEqualsToSort() {
+        String annotation = "test_annotation";
+        Intent sendIntent = createSendImageIntent(annotation);
+        String refererPackage = "test_referer_package";
+        List<ResolvedComponentInfo> resolvedComponents = createResolvedComponentsForTest(10);
+        mUsm = new UsageStatsManager(mMockContext, mMockService);
+        when(mMockContext.getSystemService(Context.USAGE_STATS_SERVICE)).thenReturn(mUsm);
+        mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
+                refererPackage, UserHandle.USER_CURRENT);
+        List<ResolvedComponentInfo> topKList = new ArrayList<>(resolvedComponents);
+        mController.topK(topKList, 5);
+        List<ResolvedComponentInfo> sortList = new ArrayList<>(topKList);
+        mController.sort(sortList);
+        assertEquals("Top k elements should be sorted when input size greater than k.",
+                sortList.subList(0, 5), topKList.subList(0, 5));
+        mController.topK(topKList, 10);
+        sortList = new ArrayList<>(topKList);
+        mController.sort(sortList);
+        assertEquals("All elements should be sorted when input size equals k.",
+                sortList, topKList);
+        mController.topK(topKList, 15);
+        sortList = new ArrayList<>(topKList);
+        mController.sort(sortList);
+        assertEquals("All elements should be sorted when input size less than k.",
+                sortList, topKList);
+    }
+
     private UsageStats initStats(String packageName, String action,
                                  String annotation, int count) {
         ArrayMap<String, ArrayMap<String, Integer>> chooserCounts = new ArrayMap<>();
@@ -156,4 +188,12 @@
         }
         return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
     }
-}
\ No newline at end of file
+
+    private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
+        List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+        for (int i = 0; i < numberOfResults; i++) {
+            infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+        }
+        return infoList;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
index 83f6bc2..9082543 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
@@ -21,6 +21,8 @@
 import android.app.usage.UsageStatsManager;
 import android.content.pm.PackageManager;
 
+import androidx.test.espresso.idling.CountingIdlingResource;
+
 import java.util.function.Function;
 
 /*
@@ -29,6 +31,12 @@
 public class ResolverWrapperActivity extends ResolverActivity {
     static final OverrideData sOverrides = new OverrideData();
     private UsageStatsManager mUsm;
+    private CountingIdlingResource mLabelIdlingResource =
+            new CountingIdlingResource("LoadLabelTask");
+
+    public CountingIdlingResource getLabelIdlingResource() {
+        return mLabelIdlingResource;
+    }
 
     ResolveListAdapter getAdapter() {
         return mAdapter;
@@ -64,6 +72,11 @@
         return super.getPackageManager();
     }
 
+    @Override
+    protected LoadLabelTask getLoadLabelTask(DisplayResolveInfo info, ViewHolder holder) {
+        return new LoadLabelWrapperTask(info, holder);
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
@@ -83,4 +96,22 @@
             resolverListController = mock(ResolverListController.class);
         }
     }
+
+    class LoadLabelWrapperTask extends LoadLabelTask {
+
+        protected LoadLabelWrapperTask(DisplayResolveInfo dri, ViewHolder holder) {
+            super(dri, holder);
+        }
+
+        @Override
+        protected void onPreExecute() {
+            mLabelIdlingResource.increment();
+        }
+
+        @Override
+        protected void onPostExecute(CharSequence[] result) {
+            super.onPostExecute(result);
+            mLabelIdlingResource.decrement();
+        }
+    }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index b93c3a7..0be5009 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -48,7 +48,6 @@
         final RegisterStatusBarResult original = new RegisterStatusBarResult(iconMap,
                 0x2 /* disabledFlags1 */,
                 0x4 /* systemUiVisibility */,
-                true /* menuVisible */,
                 0x8 /* imeWindowVis */,
                 0x10 /* imeBackDisposition */,
                 false /* showImeSwitcher */,
@@ -58,7 +57,9 @@
                 new Binder() /* imeToken */,
                 new Rect(0x100, 0x200, 0x400, 0x800) /* fullscreenStackBounds */,
                 new Rect(0x1000, 0x2000, 0x4000, 0x8000) /* dockedStackBounds */,
-                true /* navbarColorManagedByIme */);
+                true /* navbarColorManagedByIme */,
+                true /* appFullscreen */,
+                true /* appImmersive */);
 
         final RegisterStatusBarResult copy = clone(original);
 
@@ -69,7 +70,6 @@
 
         assertThat(copy.mDisabledFlags1).isEqualTo(original.mDisabledFlags1);
         assertThat(copy.mSystemUiVisibility).isEqualTo(original.mSystemUiVisibility);
-        assertThat(copy.mMenuVisible).isEqualTo(original.mMenuVisible);
         assertThat(copy.mImeWindowVis).isEqualTo(original.mImeWindowVis);
         assertThat(copy.mImeBackDisposition).isEqualTo(original.mImeBackDisposition);
         assertThat(copy.mShowImeSwitcher).isEqualTo(original.mShowImeSwitcher);
@@ -82,6 +82,8 @@
         assertThat(copy.mFullscreenStackBounds).isEqualTo(original.mFullscreenStackBounds);
         assertThat(copy.mDockedStackBounds).isEqualTo(original.mDockedStackBounds);
         assertThat(copy.mNavbarColorManagedByIme).isEqualTo(original.mNavbarColorManagedByIme);
+        assertThat(copy.mAppFullscreen).isEqualTo(original.mAppFullscreen);
+        assertThat(copy.mAppImmersive).isEqualTo(original.mAppImmersive);
     }
 
     private RegisterStatusBarResult clone(RegisterStatusBarResult original) {
diff --git a/core/tests/coretests/src/com/android/internal/widget/LockscreenCredentialTest.java b/core/tests/coretests/src/com/android/internal/widget/LockscreenCredentialTest.java
index 5eec91c..05bab1c 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LockscreenCredentialTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LockscreenCredentialTest.java
@@ -31,10 +31,23 @@
         assertEquals(0, empty.size());
         assertNotNull(empty.getCredential());
 
+        assertFalse(empty.isPin());
         assertFalse(empty.isPassword());
         assertFalse(empty.isPattern());
     }
 
+    public void testPinCredential() {
+        LockscreenCredential pin = LockscreenCredential.createPin("3456");
+
+        assertTrue(pin.isPin());
+        assertEquals(4, pin.size());
+        assertTrue(Arrays.equals("3456".getBytes(), pin.getCredential()));
+
+        assertFalse(pin.isNone());
+        assertFalse(pin.isPassword());
+        assertFalse(pin.isPattern());
+    }
+
     public void testPasswordCredential() {
         LockscreenCredential password = LockscreenCredential.createPassword("password");
 
@@ -43,6 +56,7 @@
         assertTrue(Arrays.equals("password".getBytes(), password.getCredential()));
 
         assertFalse(password.isNone());
+        assertFalse(password.isPin());
         assertFalse(password.isPattern());
     }
 
@@ -60,6 +74,7 @@
         assertTrue(Arrays.equals("12369".getBytes(), pattern.getCredential()));
 
         assertFalse(pattern.isNone());
+        assertFalse(pattern.isPin());
         assertFalse(pattern.isPassword());
     }
 
@@ -72,6 +87,15 @@
                 LockscreenCredential.createPasswordOrNone("abcd"));
     }
 
+    public void testPinOrNoneCredential() {
+        assertEquals(LockscreenCredential.createNone(),
+                LockscreenCredential.createPinOrNone(null));
+        assertEquals(LockscreenCredential.createNone(),
+                LockscreenCredential.createPinOrNone(""));
+        assertEquals(LockscreenCredential.createPin("1357"),
+                LockscreenCredential.createPinOrNone("1357"));
+    }
+
     public void testSanitize() {
         LockscreenCredential password = LockscreenCredential.createPassword("password");
         password.zeroize();
@@ -80,12 +104,15 @@
             password.isNone();
             fail("Sanitized credential still accessible");
         } catch (IllegalStateException expected) { }
-
         try {
             password.isPattern();
             fail("Sanitized credential still accessible");
         } catch (IllegalStateException expected) { }
         try {
+            password.isPin();
+            fail("Sanitized credential still accessible");
+        } catch (IllegalStateException expected) { }
+        try {
             password.isPassword();
             fail("Sanitized credential still accessible");
         } catch (IllegalStateException expected) { }
diff --git a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
index 9913531..50e8474 100644
--- a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
@@ -62,7 +62,9 @@
         Settings.Global.putInt(cr, Settings.Global.DEVICE_DEMO_MODE, deviceDemoMode);
 
         final ILockSettings ils = Mockito.mock(ILockSettings.class);
-        when(ils.havePassword(DEMO_USER_ID)).thenReturn(isSecure);
+        when(ils.getCredentialType(DEMO_USER_ID)).thenReturn(
+                isSecure ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
+                         : LockPatternUtils.CREDENTIAL_TYPE_NONE);
         when(ils.getLong("lockscreen.password_type", PASSWORD_QUALITY_UNSPECIFIED, DEMO_USER_ID))
                 .thenReturn((long) PASSWORD_QUALITY_MANAGED);
         // TODO(b/63758238): stop spying the class under test
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 4b4e416..ac742e2 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -50,6 +50,12 @@
         <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
     </privapp-permissions>
 
+    <privapp-permissions package="com.android.cellbroadcastservice">
+        <permission name="android.permission.MODIFY_PHONE_STATE"/>
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+        <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
+    </privapp-permissions>
+
     <privapp-permissions package="com.android.externalstorage">
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 34b3951..012ffcc 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -13,18 +13,24 @@
       "group": "WM_DEBUG_FOCUS_LIGHT",
       "at": "com\/android\/server\/wm\/ActivityDisplay.java"
     },
+    "-2127842445": {
+      "message": "Clearing startingData for token=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "-2109936758": {
+      "message": "removeAppToken make exiting: %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-2109864870": {
       "message": "app-release(): mOuter=%s",
       "level": "DEBUG",
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "-2086729999": {
-      "message": "Removing app token: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-2072089308": {
       "message": "Attempted to add window with token that is a sub-window: %s.  Aborting.",
       "level": "WARN",
@@ -103,24 +109,30 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
+    "-1938204785": {
+      "message": "Moving existing starting %s from %s to %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1915280162": {
       "message": "Attempted to add wallpaper window with bad token %s.  Aborting.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1886298021": {
-      "message": "setAppStartingWindow: token=%s pkg=%s transferFrom=%s newTask=%b taskSwitch=%b processRunning=%b allowTaskSnapshot=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/ActivityRecord.java"
-    },
     "-1884933373": {
       "message": "enableScreenAfterBoot: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
       "level": "INFO",
       "group": "WM_DEBUG_BOOT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-1878839956": {
+      "message": "Marking app token %s with replacing windows.",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1872288685": {
       "message": "applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b Callers=%s",
       "level": "VERBOSE",
@@ -139,18 +151,18 @@
       "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
       "at": "com\/android\/server\/wm\/AppTransition.java"
     },
+    "-1847087163": {
+      "message": "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1838803135": {
       "message": "Attempted to set windowing mode to a display that does not exist: %d",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1836092044": {
-      "message": "Creating SnapshotStartingData",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1824578273": {
       "message": "Reporting new frame to %s: %s",
       "level": "VERBOSE",
@@ -169,6 +181,12 @@
       "group": "WM_DEBUG_FOCUS",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
+    "-1782453012": {
+      "message": "Checking theme of starting window: 0x%x",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1770075711": {
       "message": "Adding window client %s that is dead, aborting.",
       "level": "WARN",
@@ -199,48 +217,42 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
-    "-1736245181": {
-      "message": "Tried to remove starting window but startingWindow was null: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1730156332": {
       "message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d",
       "level": "VERBOSE",
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayRotation.java"
     },
+    "-1715268616": {
+      "message": "Last window, removing starting window %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1710206702": {
       "message": "Display id=%d is frozen while keyguard locked, return %d",
       "level": "VERBOSE",
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
+    "-1698815688": {
+      "message": "Resetting app token %s of replacing window marks.",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1661704580": {
       "message": "Attempted to set replacing window on non-existing app token %s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1661404819": {
-      "message": "applyAnimation: atoken=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1632122349": {
       "message": "Changing surface while display frozen: %s",
       "level": "VERBOSE",
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1597650595": {
-      "message": "removeAppToken: %s delayed=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1596995693": {
       "message": "startAnimation",
       "level": "DEBUG",
@@ -259,42 +271,36 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayRotation.java"
     },
-    "-1561845439": {
-      "message": "reParentWindowToken: removing window token=%s from task=%s",
-      "level": "INFO",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1545962566": {
       "message": "View server did not start",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-1539974875": {
+      "message": "removeAppToken: %s delayed=%b Callers=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1526645239": {
       "message": "Timeout waiting for drawn: undrawn=%s",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1524305318": {
-      "message": "Nulling last startingData",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-1519226370": {
-      "message": "startingData was nulled out before handling mAddStartingWindow: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1515151503": {
       "message": ">>> OPEN TRANSACTION removeReplacedWindows",
       "level": "INFO",
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
+    "-1499134947": {
+      "message": "Removing starting %s from %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1497837552": {
       "message": "onAnimationFinished(): mPendingAnimations=%d",
       "level": "DEBUG",
@@ -307,11 +313,17 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/AppWindowThumbnail.java"
     },
-    "-1470632028": {
-      "message": "Marking app token %s with replacing windows.",
+    "-1471946192": {
+      "message": "Marking app token %s with replacing child windows.",
       "level": "DEBUG",
       "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "-1456549051": {
+      "message": "setClientHidden: %s clientHidden=%b Callers=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "-1455600136": {
       "message": "Attempted to add Dream window with unknown token %s.  Aborting.",
@@ -319,12 +331,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1448427933": {
-      "message": "startingWindow was set but startingSurface==null, couldn't remove",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1443029505": {
       "message": "SAFE MODE ENABLED (menu=%d s=%d dpad=%d trackball=%d)",
       "level": "INFO",
@@ -361,17 +367,29 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-1352076759": {
+      "message": "Removing app token: %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1350198040": {
       "message": "hideBootMessagesLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
       "level": "INFO",
       "group": "WM_DEBUG_BOOT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "-1318134223": {
-      "message": "No longer Stopped: %s",
+    "-1340540100": {
+      "message": "Creating SnapshotStartingData",
       "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "-1292329638": {
+      "message": "Added starting %s: startingWindow=%s startingView=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "-1270731689": {
       "message": "Attempted to set replacing window on app token with no content %s",
@@ -445,6 +463,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "-1128015008": {
+      "message": "Schedule remove starting %s startingWindow=%s startingView=%s Callers=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-1117599386": {
       "message": "Deferring rotation, display is not enabled.",
       "level": "VERBOSE",
@@ -475,23 +499,17 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "-1097148233": {
-      "message": "commitVisibility: %s: hidden=%b hiddenRequested=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-1089874824": {
       "message": "SURFACE SHOW (performLayout): %s",
       "level": "INFO",
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
     },
-    "-1077196445": {
-      "message": "Add starting %s: startingData=%s",
+    "-1088782910": {
+      "message": "Translucent=%s Floating=%s ShowWallpaper=%s",
       "level": "VERBOSE",
       "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "-1076978367": {
       "message": "thawRotation: mRotation=%d",
@@ -529,12 +547,6 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
-    "-1001633850": {
-      "message": "Removing focused app token:%s displayId=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_FOCUS_LIGHT",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-993378225": {
       "message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s",
       "level": "VERBOSE",
@@ -547,23 +559,11 @@
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
-    "-979259577": {
-      "message": "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
+    "-931184679": {
+      "message": "Changing app %s hidden=%b performLayout=%b",
       "level": "VERBOSE",
       "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-955458843": {
-      "message": "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
-      "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "-953872371": {
-      "message": "setClientHidden: %s clientHidden=%b Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "-928291778": {
       "message": "applyAnimation: anim=%s nextAppTransition=%d transit=%s Callers=%s",
@@ -631,12 +631,6 @@
       "group": "WM_DEBUG_FOCUS_LIGHT",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
-    "-807062773": {
-      "message": "Aborted starting %s: removed=%b startingData=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-793346159": {
       "message": "New transit into wallpaper: %s",
       "level": "VERBOSE",
@@ -661,6 +655,12 @@
       "group": "WM_DEBUG_FOCUS_LIGHT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-771177730": {
+      "message": "Removing focused app token:%s displayId=%d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_FOCUS_LIGHT",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-760801764": {
       "message": "onAnimationCancelled",
       "level": "DEBUG",
@@ -703,12 +703,6 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
-    "-666419717": {
-      "message": "Creating animation bounds layer",
-      "level": "INFO",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-653156702": {
       "message": "createAppAnimations()",
       "level": "DEBUG",
@@ -751,12 +745,6 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayRotation.java"
     },
-    "-573268667": {
-      "message": "applyAnimation: transition animation is disabled or skipped. atoken=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-554834595": {
       "message": "Display id=%d is frozen, return %d",
       "level": "VERBOSE",
@@ -817,6 +805,12 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
     },
+    "-443173857": {
+      "message": "Moving pending starting from %s to %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-439951996": {
       "message": "Disabling listeners",
       "level": "VERBOSE",
@@ -865,24 +859,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
-    "-367797467": {
-      "message": "Creating SplashScreenStartingData",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-344488673": {
       "message": "Finishing drawing window %s: mDrawState=%s",
       "level": "VERBOSE",
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
     },
-    "-336658140": {
-      "message": "Checking theme of starting window: 0x%x",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-324085783": {
       "message": "SURFACE CROP %s: %s",
       "level": "INFO",
@@ -901,6 +883,18 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "-253016819": {
+      "message": "applyAnimation: transition animation is disabled or skipped. atoken=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "-251259736": {
+      "message": "No longer freezing: %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "-198463978": {
       "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
       "level": "VERBOSE",
@@ -943,12 +937,6 @@
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimation.java"
     },
-    "-104758113": {
-      "message": "Removing app %s delayed=%b animation=%s animating=%b",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-96848838": {
       "message": "Gaining focus: %s",
       "level": "INFO",
@@ -973,12 +961,6 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/Session.java"
     },
-    "-34965929": {
-      "message": "Moving pending starting from %s to %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "-29233992": {
       "message": "SURFACE CLEAR CROP: %s",
       "level": "INFO",
@@ -1021,11 +1003,17 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "44171776": {
-      "message": "Resetting app token %s of replacing window marks.",
-      "level": "DEBUG",
+    "44438983": {
+      "message": "performLayout: Activity exiting now removed %s",
+      "level": "VERBOSE",
       "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "at": "com\/android\/server\/wm\/DisplayContent.java"
+    },
+    "45285419": {
+      "message": "startingWindow was set but startingSurface==null, couldn't remove",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "51200510": {
       "message": "  BLACK %s: DESTROY",
@@ -1069,17 +1057,11 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
-    "115108840": {
-      "message": "Removing startingView=%s",
+    "108170907": {
+      "message": "Add starting %s: startingData=%s",
       "level": "VERBOSE",
       "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "118187173": {
-      "message": "Enqueueing ADD_STARTING",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "123161180": {
       "message": "SEVER CHILDREN",
@@ -1087,6 +1069,12 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
     },
+    "146871307": {
+      "message": "Tried to remove starting window but startingWindow was null: %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "150351993": {
       "message": "addWindow: %s startingWindow=%s",
       "level": "VERBOSE",
@@ -1099,18 +1087,6 @@
       "group": "WM_SHOW_SURFACE_ALLOC",
       "at": "com\/android\/server\/wm\/BlackFrame.java"
     },
-    "154699456": {
-      "message": "Last window, removing starting window %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "173419252": {
-      "message": "No thumbnail header bitmap for: %d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "184362060": {
       "message": "screenshotTask(%d): mCanceled=%b",
       "level": "DEBUG",
@@ -1129,12 +1105,6 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "196230599": {
-      "message": "Moving existing starting %s from %s to %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "221540118": {
       "message": "mUserActivityTimeout set to %d",
       "level": "DEBUG",
@@ -1237,12 +1207,24 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "358613119": {
+      "message": "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "371641947": {
       "message": "Window Manager Crash %s",
       "level": "WTF",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "372792199": {
+      "message": "Non-null activity for system window of rootType=%d",
+      "level": "WARN",
+      "group": "WM_ERROR",
+      "at": "com\/android\/server\/wm\/WindowManagerService.java"
+    },
     "374972436": {
       "message": "performEnableScreen: Waiting for anim complete",
       "level": "INFO",
@@ -1255,18 +1237,18 @@
       "group": "WM_DEBUG_FOCUS_LIGHT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "393054329": {
+      "message": "reParentWindowToken: removing window token=%s from task=%s",
+      "level": "INFO",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "399841913": {
       "message": "SURFACE RECOVER DESTROY: %s",
       "level": "INFO",
       "group": "WM_SHOW_SURFACE_ALLOC",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
-    "416664944": {
-      "message": "No longer freezing: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "417311568": {
       "message": "onResize: Resizing %s",
       "level": "DEBUG",
@@ -1315,12 +1297,6 @@
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimation.java"
     },
-    "492980365": {
-      "message": "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "495032901": {
       "message": "Expected target stack=%s to restored behind stack=%s but it is behind stack=%s",
       "level": "WARN",
@@ -1333,6 +1309,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
       "at": "com\/android\/server\/wm\/AppTransition.java"
     },
+    "539077569": {
+      "message": "Clear freezing of %s force=%b",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "557227556": {
       "message": "onAnimationFinished(): Notify animation finished:",
       "level": "DEBUG",
@@ -1417,12 +1399,6 @@
       "group": "WM_DEBUG_SCREEN_ON",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "668425960": {
-      "message": "Notify removed startingWindow %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "676824470": {
       "message": "Test completed successfully: %b %d %o %x %e %g %f %% %s.",
       "level": "ERROR",
@@ -1459,18 +1435,18 @@
       "group": "WM_SHOW_SURFACE_ALLOC",
       "at": "com\/android\/server\/wm\/WindowStateAnimator.java"
     },
-    "758852025": {
-      "message": "Surface returned was null: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "765395228": {
       "message": "onAnimationFinished(): controller=%s reorderMode=%d",
       "level": "DEBUG",
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimation.java"
     },
+    "789829331": {
+      "message": "Aborted starting %s: removed=%b startingData=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "791468751": {
       "message": "Pausing rotation during re-position",
       "level": "DEBUG",
@@ -1483,11 +1459,17 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
-    "811802785": {
-      "message": "Changing app %s hidden=%b performLayout=%b",
+    "806891543": {
+      "message": "Setting mOrientationChangeComplete=true because wtoken %s numInteresting=%d numDrawn=%d",
+      "level": "INFO",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "815803557": {
+      "message": "applyAnimation: atoken=%s",
       "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "829434921": {
       "message": "Draw state now committed in %s",
@@ -1507,23 +1489,17 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
-    "847534382": {
-      "message": "Non-null appWindowToken for system window of rootType=%d",
-      "level": "WARN",
-      "group": "WM_ERROR",
-      "at": "com\/android\/server\/wm\/WindowManagerService.java"
-    },
     "853091290": {
       "message": "Moved stack=%s behind stack=%s",
       "level": "DEBUG",
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimation.java"
     },
-    "868946719": {
-      "message": "notifyAppResumed: wasStopped=%b %s",
+    "857751535": {
+      "message": "commitVisibility: %s: hidden=%b hiddenRequested=%b",
       "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "873914452": {
       "message": "goodToGo()",
@@ -1531,12 +1507,6 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "884043983": {
-      "message": "removeDeadWindows: %s",
-      "level": "WARN",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "892244061": {
       "message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d",
       "level": "INFO",
@@ -1573,12 +1543,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "990058731": {
-      "message": "notifyAppStopped: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1001904964": {
       "message": "***** BOOT TIMEOUT: forcing display enabled",
       "level": "WARN",
@@ -1591,12 +1555,6 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
-    "1021057640": {
-      "message": "Marking app token %s with replacing child windows.",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1051545910": {
       "message": "Exit animation finished in %s: remove=%b",
       "level": "VERBOSE",
@@ -1651,12 +1609,6 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
-    "1195433019": {
-      "message": "Clearing startingData for token=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1208313423": {
       "message": "addWindowToken: Attempted to add token: %s for non-exiting displayId=%d",
       "level": "WARN",
@@ -1675,17 +1627,23 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
     },
+    "1224184681": {
+      "message": "No longer Stopped: %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1224307091": {
       "message": "checkBootAnimationComplete: Animation complete!",
       "level": "INFO",
       "group": "WM_DEBUG_BOOT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1244668962": {
-      "message": "Added starting %s: startingWindow=%s startingView=%s",
+    "1254403969": {
+      "message": "Surface returned was null: %s",
       "level": "VERBOSE",
       "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "1288731814": {
       "message": "WindowState.hideLw: setting mFocusMayChange true",
@@ -1717,17 +1675,29 @@
       "group": "WM_DEBUG_FOCUS",
       "at": "com\/android\/server\/wm\/DisplayContent.java"
     },
+    "1358786604": {
+      "message": "No thumbnail header bitmap for: %d",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "1364498663": {
+      "message": "notifyAppResumed: wasStopped=%b %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1401700824": {
       "message": "Window drawn win=%s",
       "level": "DEBUG",
       "group": "WM_DEBUG_SCREEN_ON",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1404220922": {
-      "message": "Translucent=%s Floating=%s ShowWallpaper=%s",
+    "1417601133": {
+      "message": "Enqueueing ADD_STARTING",
       "level": "VERBOSE",
       "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "1422781269": {
       "message": "Resuming rotation after re-position",
@@ -1783,12 +1753,6 @@
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
     },
-    "1496418389": {
-      "message": "Removing starting %s from %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1497304204": {
       "message": "Deferring rotation, rotation is paused.",
       "level": "VERBOSE",
@@ -1801,6 +1765,12 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "1515161239": {
+      "message": "removeDeadWindows: %s",
+      "level": "WARN",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1518495446": {
       "message": "removeWindowToken: Attempted to remove non-existing token: %s",
       "level": "WARN",
@@ -1873,11 +1843,29 @@
       "group": "WM_DEBUG_RESIZE",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
-    "1637745145": {
-      "message": "Clear freezing of %s force=%b",
+    "1653210583": {
+      "message": "Removing app %s delayed=%b animation=%s animating=%b",
       "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "1671994402": {
+      "message": "Nulling last startingData",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "1677260366": {
+      "message": "Finish starting %s: first real window is shown, no animation",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "1720229827": {
+      "message": "Creating animation bounds layer",
+      "level": "INFO",
+      "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "1720696061": {
       "message": "Adding window to Display that has been removed.",
@@ -1891,6 +1879,12 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "1742235936": {
+      "message": "Removing startingView=%s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1747941491": {
       "message": "SURFACE controller=%s alpha=%f matrix=[%f*%f,%f*%f][%f*%f,%f*%f]: %s",
       "level": "INFO",
@@ -1909,23 +1903,23 @@
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RecentsAnimation.java"
     },
-    "1764592478": {
-      "message": "reparent: moving app token=%s to task=%d at %d",
-      "level": "INFO",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1774661765": {
       "message": "Devices still not ready after waiting %d milliseconds before attempting to detect safe mode.",
       "level": "WARN",
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1814552834": {
-      "message": "performLayout: App token exiting now removed %s",
+    "1804869745": {
+      "message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
+    "1836214582": {
+      "message": "startingData was nulled out before handling mAddStartingWindow: %s",
       "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "1836306327": {
       "message": "Skipping set freeze of %s",
@@ -1933,6 +1927,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1853793312": {
+      "message": "Notify removed startingWindow %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1865125884": {
       "message": "finishScreenTurningOn: mAwake=%b, mScreenOnEarly=%b, mScreenOnFully=%b, mKeyguardDrawComplete=%b, mWindowManagerDrawComplete=%b",
       "level": "DEBUG",
@@ -1951,24 +1951,18 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "1878395049": {
-      "message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
-    "1883987026": {
-      "message": "removeAppToken make exiting: %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "1891501279": {
       "message": "cancelAnimation(): reason=%s",
       "level": "DEBUG",
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
+    "1903353011": {
+      "message": "notifyAppStopped: %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1921821199": {
       "message": "Preserving %s until the new one is added",
       "level": "VERBOSE",
@@ -1987,29 +1981,29 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
+    "1966564525": {
+      "message": "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
+      "level": "INFO",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "1984470582": {
       "message": "Creating TaskScreenshotAnimatable: task: %s width: %d height: %d",
       "level": "DEBUG",
       "group": "WM_DEBUG_RECENTS_ANIMATIONS",
       "at": "com\/android\/server\/wm\/TaskScreenshotAnimatable.java"
     },
-    "1984738415": {
-      "message": "Now animating app in place %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_APP_TRANSITIONS",
-      "at": "com\/android\/server\/wm\/AppTransitionController.java"
-    },
     "1984782949": {
       "message": ">>> OPEN TRANSACTION animate",
       "level": "INFO",
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowAnimator.java"
     },
-    "1993685727": {
-      "message": "Setting mOrientationChangeComplete=true because wtoken %s numInteresting=%d numDrawn=%d",
+    "1995048598": {
+      "message": "reparent: moving app token=%s to task=%d at %d",
       "level": "INFO",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
     "2016061474": {
       "message": "Prepare app transition: transit=%s %s alwaysKeepCurrent=%b displayId=%d Callers=%s",
@@ -2023,6 +2017,12 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "2018852077": {
+      "message": "Creating SplashScreenStartingData",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_STARTING_WINDOW",
+      "at": "com\/android\/server\/wm\/ActivityRecord.java"
+    },
     "2028163120": {
       "message": "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s isEntrance=%s Callers=%s",
       "level": "VERBOSE",
@@ -2041,24 +2041,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
-    "2054958632": {
-      "message": "Schedule remove starting %s startingWindow=%s startingView=%s Callers=%s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "2057434754": {
       "message": "\tvisible=%s",
       "level": "DEBUG",
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
     },
-    "2076259606": {
-      "message": "Finish starting %s: first real window is shown, no animation",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_STARTING_WINDOW",
-      "at": "com\/android\/server\/wm\/AppWindowToken.java"
-    },
     "2083556954": {
       "message": "Set mOrientationChanging of %s",
       "level": "VERBOSE",
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 4471017..d900a42 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1359,9 +1359,44 @@
      * Specifies the known formats a bitmap can be compressed into
      */
     public enum CompressFormat {
-        JPEG    (0),
-        PNG     (1),
-        WEBP    (2);
+        /**
+         * Compress to the JPEG format. {@code quality} of {@code 0} means
+         * compress for the smallest size. {@code 100} means compress for max
+         * visual quality.
+         */
+        JPEG          (0),
+        /**
+         * Compress to the PNG format. PNG is lossless, so {@code quality} is
+         * ignored.
+         */
+        PNG           (1),
+        /**
+         * Compress to the WEBP format. {@code quality} of {@code 0} means
+         * compress for the smallest size. {@code 100} means compress for max
+         * visual quality. As of {@link android.os.Build.VERSION_CODES#Q}, a
+         * value of {@code 100} results in a file in the lossless WEBP format.
+         * Otherwise the file will be in the lossy WEBP format.
+         *
+         * @deprecated in favor of the more explicit
+         *             {@link CompressFormat#WEBP_LOSSY} and
+         *             {@link CompressFormat#WEBP_LOSSLESS}.
+         */
+        @Deprecated
+        WEBP          (2),
+        /**
+         * Compress to the WEBP lossy format. {@code quality} of {@code 0} means
+         * compress for the smallest size. {@code 100} means compress for max
+         * visual quality.
+         */
+        WEBP_LOSSY    (3),
+        /**
+         * Compress to the WEBP lossless format. {@code quality} refers to how
+         * much effort to put into compression. A value of {@code 0} means to
+         * compress quickly, resulting in a relatively large file size.
+         * {@code 100} means to spend more time compressing, resulting in a
+         * smaller file.
+         */
+        WEBP_LOSSLESS (4);
 
         CompressFormat(int nativeInt) {
             this.nativeInt = nativeInt;
@@ -1385,10 +1420,8 @@
      * pixels).
      *
      * @param format   The format of the compressed image
-     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
-     *                 small size, 100 meaning compress for max quality. Some
-     *                 formats, like PNG which is lossless, will ignore the
-     *                 quality setting
+     * @param quality  Hint to the compressor, 0-100. The value is interpreted
+     *                 differently depending on the {@link CompressFormat}.
      * @param stream   The outputstream to write the compressed data.
      * @return true if successfully compressed to the specified stream.
      */
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 9c4b5e8..06d4fbd 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -1380,9 +1380,9 @@
      */
     @NonNull
     static ColorSpace get(@IntRange(from = MIN_ID, to = MAX_ID) int index) {
-        if (index < 0 || index >= Named.values().length) {
+        if (index < 0 || index >= sNamedColorSpaces.length) {
             throw new IllegalArgumentException("Invalid ID, must be in the range [0.." +
-                    Named.values().length + ")");
+                    sNamedColorSpaces.length + ")");
         }
         return sNamedColorSpaces[index];
     }
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 54995ac..f25910b 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -71,6 +71,15 @@
     /** Key containing suffix of lockdown VPN profile. */
     public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN";
 
+    /** Name of CA certificate usage. */
+    public static final String CERTIFICATE_USAGE_CA = "ca";
+
+    /** Name of User certificate usage. */
+    public static final String CERTIFICATE_USAGE_USER = "user";
+
+    /** Name of WIFI certificate usage. */
+    public static final String CERTIFICATE_USAGE_WIFI = "wifi";
+
     /** Data type for public keys. */
     public static final String EXTRA_PUBLIC_KEY = "KEY";
 
@@ -91,6 +100,11 @@
     public static final String EXTRA_INSTALL_AS_UID = "install_as_uid";
 
     /**
+     * Intent extra: type of the certificate to install
+     */
+    public static final String EXTRA_CERTIFICATE_USAGE = "certificate_install_usage";
+
+    /**
      * Intent extra: name for the user's key pair.
      */
     public static final String EXTRA_USER_KEY_ALIAS = "user_key_pair_name";
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index a34a6c0..4f52a88 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -167,8 +167,9 @@
         },
     },
     data: [
-      "tests/data/**/*.apk",
-      "tests/data/**/*.arsc",
+        "tests/data/**/*.apk",
+        "tests/data/**/*.arsc",
+        "tests/data/**/*.idmap",
     ],
     test_suites: ["device-tests"],
 }
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index b309621..16dbbf6 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -45,7 +45,7 @@
                      time_t last_mod_time,
                      bool for_loader)
     : zip_handle_(unmanaged_handle, ::CloseArchive), path_(path), last_mod_time_(last_mod_time),
-      for_loader(for_loader) {
+      for_loader_(for_loader) {
 }
 
 std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system,
@@ -75,7 +75,7 @@
     return {};
   }
   return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(), std::move(idmap_asset),
-                  std::move(loaded_idmap), system, false /*load_as_shared_library*/);
+                  std::move(loaded_idmap), system, true /*load_as_shared_library*/);
 }
 
 std::unique_ptr<const ApkAssets> ApkAssets::LoadFromFd(unique_fd fd,
@@ -165,12 +165,14 @@
 
   // Must retain ownership of the IDMAP Asset so that all pointers to its mmapped data remain valid.
   loaded_apk->idmap_asset_ = std::move(idmap_asset);
+  loaded_apk->loaded_idmap_ = std::move(loaded_idmap);
 
   const StringPiece data(
       reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
       loaded_apk->resources_asset_->getLength());
   loaded_apk->loaded_arsc_ =
-      LoadedArsc::Load(data, loaded_idmap.get(), system, load_as_shared_library, for_loader);
+      LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(), system, load_as_shared_library,
+                       for_loader);
   if (loaded_apk->loaded_arsc_ == nullptr) {
     LOG(ERROR) << "Failed to load '" << kResourcesArsc << "' in APK '" << path << "'.";
     return {};
@@ -319,7 +321,7 @@
 
 bool ApkAssets::IsUpToDate() const {
   // Loaders are invalidated by the app, not the system, so assume up to date
-  if (for_loader) {
+  if (for_loader_) {
     return true;
   }
 
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index e914f37..ca4143f 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -25,6 +25,7 @@
 
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
+#include "androidfw/ResourceUtils.h"
 #include "androidfw/Util.h"
 #include "utils/ByteOrder.h"
 #include "utils/Trace.h"
@@ -35,15 +36,13 @@
 #endif
 #endif
 
-#include "androidfw/ResourceUtils.h"
-
 namespace android {
 
 struct FindEntryResult {
   // A pointer to the resource table entry for this resource.
   // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
   // a ResTable_map_entry and processed as a bag/map.
-  const ResTable_entry* entry;
+  ResTable_entry_handle entry;
 
   // The configuration for which the resulting entry was defined. This is already swapped to host
   // endianness.
@@ -55,6 +54,9 @@
   // The dynamic package ID map for the package from which this resource came from.
   const DynamicRefTable* dynamic_ref_table;
 
+  // The package name of the resource.
+  const std::string* package_name;
+
   // The string pool reference to the type's name. This uses a different string pool than
   // the global string pool, but this is hidden from the caller.
   StringPoolRef type_string_ref;
@@ -83,11 +85,15 @@
   package_groups_.clear();
   package_ids_.fill(0xff);
 
+  // A mapping from apk assets path to the runtime package id of its first loaded package.
+  std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
+
   // 0x01 is reserved for the android package.
   int next_package_id = 0x02;
   const size_t apk_assets_count = apk_assets_.size();
   for (size_t i = 0; i < apk_assets_count; i++) {
-    const LoadedArsc* loaded_arsc = apk_assets_[i]->GetLoadedArsc();
+    const ApkAssets* apk_assets = apk_assets_[i];
+    const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
 
     for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) {
       // Get the package ID or assign one if a shared library.
@@ -103,9 +109,37 @@
       if (idx == 0xff) {
         package_ids_[package_id] = idx = static_cast<uint8_t>(package_groups_.size());
         package_groups_.push_back({});
-        DynamicRefTable& ref_table = package_groups_.back().dynamic_ref_table;
-        ref_table.mAssignedPackageId = package_id;
-        ref_table.mAppAsLib = package->IsDynamic() && package->GetPackageId() == 0x7f;
+
+        if (apk_assets->IsOverlay()) {
+          // The target package must precede the overlay package in the apk assets paths in order
+          // to take effect.
+          const auto& loaded_idmap = apk_assets->GetLoadedIdmap();
+          auto target_package_iter = apk_assets_package_ids.find(loaded_idmap->TargetApkPath());
+          if (target_package_iter != apk_assets_package_ids.end()) {
+            const uint8_t target_package_id = target_package_iter->second;
+            const uint8_t target_idx = package_ids_[target_package_id];
+            CHECK(target_idx != 0xff) << "overlay added to apk_assets_package_ids but does not"
+                                      << " have an assigned package group";
+
+            PackageGroup& target_package_group = package_groups_[target_idx];
+
+            // Create a special dynamic reference table for the overlay to rewite references to
+            // overlay resources as references to the target resources they overlay.
+            auto overlay_table = std::make_shared<OverlayDynamicRefTable>(
+                loaded_idmap->GetOverlayDynamicRefTable(target_package_id));
+            package_groups_.back().dynamic_ref_table = overlay_table;
+
+            // Add the overlay resource map to the target package's set of overlays.
+            target_package_group.overlays_.push_back(
+                ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id,
+                                                                      overlay_table.get()),
+                                  static_cast<ApkAssetsCookie>(i)});
+          }
+        }
+
+        DynamicRefTable* ref_table = package_groups_.back().dynamic_ref_table.get();
+        ref_table->mAssignedPackageId = package_id;
+        ref_table->mAppAsLib = package->IsDynamic() && package->GetPackageId() == 0x7f;
       }
       PackageGroup* package_group = &package_groups_[idx];
 
@@ -116,9 +150,11 @@
       // Add the package name -> build time ID mappings.
       for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
         String16 package_name(entry.package_name.c_str(), entry.package_name.size());
-        package_group->dynamic_ref_table.mEntries.replaceValueFor(
+        package_group->dynamic_ref_table->mEntries.replaceValueFor(
             package_name, static_cast<uint8_t>(entry.package_id));
       }
+
+      apk_assets_package_ids.insert(std::make_pair(apk_assets->GetPath(), package_id));
     }
   }
 
@@ -127,8 +163,8 @@
   for (auto iter = package_groups_.begin(); iter != package_groups_end; ++iter) {
     const std::string& package_name = iter->packages_[0].loaded_package_->GetPackageName();
     for (auto iter2 = package_groups_.begin(); iter2 != package_groups_end; ++iter2) {
-      iter2->dynamic_ref_table.addMapping(String16(package_name.c_str(), package_name.size()),
-                                          iter->dynamic_ref_table.mAssignedPackageId);
+      iter2->dynamic_ref_table->addMapping(String16(package_name.c_str(), package_name.size()),
+                                           iter->dynamic_ref_table->mAssignedPackageId);
     }
   }
 }
@@ -161,13 +197,13 @@
                           (loaded_package->IsDynamic() ? " dynamic" : ""));
     }
     LOG(INFO) << base::StringPrintf("PG (%02x): ",
-                                    package_group.dynamic_ref_table.mAssignedPackageId)
+                                    package_group.dynamic_ref_table->mAssignedPackageId)
               << list;
 
     for (size_t i = 0; i < 256; i++) {
-      if (package_group.dynamic_ref_table.mLookupTable[i] != 0) {
+      if (package_group.dynamic_ref_table->mLookupTable[i] != 0) {
         LOG(INFO) << base::StringPrintf("    e[0x%02x] -> 0x%02x", (uint8_t) i,
-                                        package_group.dynamic_ref_table.mLookupTable[i]);
+                                        package_group.dynamic_ref_table->mLookupTable[i]);
       }
     }
   }
@@ -189,14 +225,15 @@
   if (idx == 0xff) {
     return nullptr;
   }
-  return &package_groups_[idx].dynamic_ref_table;
+  return package_groups_[idx].dynamic_ref_table.get();
 }
 
-const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const {
+std::shared_ptr<const DynamicRefTable> AssetManager2::GetDynamicRefTableForCookie(
+    ApkAssetsCookie cookie) const {
   for (const PackageGroup& package_group : package_groups_) {
     for (const ApkAssetsCookie& package_cookie : package_group.cookies_) {
       if (package_cookie == cookie) {
-        return &package_group.dynamic_ref_table;
+        return package_group.dynamic_ref_table;
       }
     }
   }
@@ -290,21 +327,45 @@
   }
 }
 
-std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
-                                                                   bool exclude_mipmap) const {
-  ATRACE_NAME("AssetManager::GetResourceConfigurations");
-  std::set<ResTable_config> configurations;
+std::set<std::string> AssetManager2::GetNonSystemOverlayPaths() const {
+  std::set<std::string> non_system_overlays;
   for (const PackageGroup& package_group : package_groups_) {
     bool found_system_package = false;
     for (const ConfiguredPackage& package : package_group.packages_) {
-      if (exclude_system && package.loaded_package_->IsSystem()) {
+      if (package.loaded_package_->IsSystem()) {
         found_system_package = true;
+        break;
+      }
+    }
+
+    if (!found_system_package) {
+      for (const ConfiguredOverlay& overlay : package_group.overlays_) {
+        non_system_overlays.insert(apk_assets_[overlay.cookie]->GetPath());
+      }
+    }
+  }
+
+  return non_system_overlays;
+}
+
+std::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
+                                                                   bool exclude_mipmap) const {
+  ATRACE_NAME("AssetManager::GetResourceConfigurations");
+  const auto non_system_overlays =
+      (exclude_system) ? GetNonSystemOverlayPaths() : std::set<std::string>();
+
+  std::set<ResTable_config> configurations;
+  for (const PackageGroup& package_group : package_groups_) {
+    for (size_t i = 0; i < package_group.packages_.size(); i++) {
+      const ConfiguredPackage& package = package_group.packages_[i];
+      if (exclude_system && package.loaded_package_->IsSystem()) {
         continue;
       }
 
-      if (exclude_system && package.loaded_package_->IsOverlay() && found_system_package) {
-        // Overlays must appear after the target package to take effect. Any overlay found in the
-        // same package as a system package is able to overlay system resources.
+      auto apk_assets = apk_assets_[package_group.cookies_[i]];
+      if (exclude_system && apk_assets->IsOverlay()
+          && non_system_overlays.find(apk_assets->GetPath()) == non_system_overlays.end()) {
+        // Exclude overlays that target system resources.
         continue;
       }
 
@@ -318,17 +379,20 @@
                                                         bool merge_equivalent_languages) const {
   ATRACE_NAME("AssetManager::GetResourceLocales");
   std::set<std::string> locales;
+  const auto non_system_overlays =
+      (exclude_system) ? GetNonSystemOverlayPaths() : std::set<std::string>();
+
   for (const PackageGroup& package_group : package_groups_) {
-    bool found_system_package = false;
-    for (const ConfiguredPackage& package : package_group.packages_) {
+    for (size_t i = 0; i < package_group.packages_.size(); i++) {
+      const ConfiguredPackage& package = package_group.packages_[i];
       if (exclude_system && package.loaded_package_->IsSystem()) {
-        found_system_package = true;
         continue;
       }
 
-      if (exclude_system && package.loaded_package_->IsOverlay() && found_system_package) {
-        // Overlays must appear after the target package to take effect. Any overlay found in the
-        // same package as a system package is able to overlay system resources.
+      auto apk_assets = apk_assets_[package_group.cookies_[i]];
+      if (exclude_system && apk_assets->IsOverlay()
+          && non_system_overlays.find(apk_assets->GetPath()) == non_system_overlays.end()) {
+        // Exclude overlays that target system resources.
         continue;
       }
 
@@ -424,6 +488,12 @@
                                          bool /*stop_at_first_match*/,
                                          bool ignore_configuration,
                                          FindEntryResult* out_entry) const {
+  if (resource_resolution_logging_enabled_) {
+    // Clear the last logged resource resolution.
+    ResetResourceResolution();
+    last_resolution_.resid = resid;
+  }
+
   // Might use this if density_override != 0.
   ResTable_config density_override_config;
 
@@ -435,6 +505,7 @@
     desired_config = &density_override_config;
   }
 
+  // Retrieve the package group from the package id of the resource id.
   if (!is_valid_resid(resid)) {
     LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
     return kInvalidCookie;
@@ -443,8 +514,7 @@
   const uint32_t package_id = get_package_id(resid);
   const uint8_t type_idx = get_type_id(resid) - 1;
   const uint16_t entry_idx = get_entry_id(resid);
-
-  const uint8_t package_idx = package_ids_[package_id];
+  uint8_t package_idx = package_ids_[package_id];
   if (package_idx == 0xff) {
     ANDROID_LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.",
                                              package_id, resid);
@@ -452,8 +522,71 @@
   }
 
   const PackageGroup& package_group = package_groups_[package_idx];
-  const size_t package_count = package_group.packages_.size();
+  ApkAssetsCookie cookie = FindEntryInternal(package_group, type_idx, entry_idx, *desired_config,
+                                             false /* stop_at_first_match */,
+                                             ignore_configuration, out_entry);
+  if (UNLIKELY(cookie == kInvalidCookie)) {
+    return kInvalidCookie;
+  }
 
+  if (!apk_assets_[cookie]->IsLoader()) {
+    for (const auto& id_map : package_group.overlays_) {
+      auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid);
+      if (!overlay_entry) {
+        // No id map entry exists for this target resource.
+        continue;
+      }
+
+      if (overlay_entry.IsTableEntry()) {
+        // The target resource is overlaid by an inline value not represented by a resource.
+        out_entry->entry = overlay_entry.GetTableEntry();
+        out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
+        cookie = id_map.cookie;
+        continue;
+      }
+
+      FindEntryResult overlay_result;
+      ApkAssetsCookie overlay_cookie = FindEntry(overlay_entry.GetResourceId(), density_override,
+                                                 false /* stop_at_first_match */,
+                                                 ignore_configuration, &overlay_result);
+      if (UNLIKELY(overlay_cookie == kInvalidCookie)) {
+        continue;
+      }
+
+      if (!overlay_result.config.isBetterThan(out_entry->config, desired_config)
+          && overlay_result.config.compare(out_entry->config) != 0) {
+        // The configuration of the entry for the overlay must be equal to or better than the target
+        // configuration to be chosen as the better value.
+        continue;
+      }
+
+      cookie = overlay_cookie;
+      out_entry->entry = std::move(overlay_result.entry);
+      out_entry->config = overlay_result.config;
+      out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
+      if (resource_resolution_logging_enabled_) {
+        last_resolution_.steps.push_back(
+            Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result.config.toString(),
+                             &package_group.packages_[0].loaded_package_->GetPackageName()});
+      }
+    }
+  }
+
+  if (resource_resolution_logging_enabled_) {
+    last_resolution_.cookie = cookie;
+    last_resolution_.type_string_ref = out_entry->type_string_ref;
+    last_resolution_.entry_string_ref = out_entry->entry_string_ref;
+  }
+
+  return cookie;
+}
+
+ApkAssetsCookie AssetManager2::FindEntryInternal(const PackageGroup& package_group,
+                                                 uint8_t type_idx, uint16_t entry_idx,
+                                                 const ResTable_config& desired_config,
+                                                 bool /*stop_at_first_match*/,
+                                                 bool ignore_configuration,
+                                                 FindEntryResult* out_entry) const {
   ApkAssetsCookie best_cookie = kInvalidCookie;
   const LoadedPackage* best_package = nullptr;
   const ResTable_type* best_type = nullptr;
@@ -462,13 +595,14 @@
   uint32_t best_offset = 0u;
   uint32_t type_flags = 0u;
 
-  Resolution::Step::Type resolution_type;
+  Resolution::Step::Type resolution_type = Resolution::Step::Type::NO_ENTRY;
   std::vector<Resolution::Step> resolution_steps;
 
   // If desired_config is the same as the set configuration, then we can use our filtered list
   // and we don't need to match the configurations, since they already matched.
-  const bool use_fast_path = !ignore_configuration && desired_config == &configuration_;
+  const bool use_fast_path = !ignore_configuration && &desired_config == &configuration_;
 
+  const size_t package_count = package_group.packages_.size();
   for (size_t pi = 0; pi < package_count; pi++) {
     const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
     const LoadedPackage* loaded_package = loaded_package_impl.loaded_package_;
@@ -481,24 +615,10 @@
       continue;
     }
 
-    uint16_t local_entry_idx = entry_idx;
-
-    // If there is an IDMAP supplied with this package, translate the entry ID.
-    if (type_spec->idmap_entries != nullptr) {
-      if (!LoadedIdmap::Lookup(type_spec->idmap_entries, local_entry_idx, &local_entry_idx)) {
-        // There is no mapping, so the resource is not meant to be in this overlay package.
-        continue;
-      }
-    }
-
-    type_flags |= type_spec->GetFlagsForEntryIndex(local_entry_idx);
-
-
     // If the package is an overlay or custom loader,
     // then even configurations that are the same MUST be chosen.
-    const bool package_is_overlay = loaded_package->IsOverlay();
     const bool package_is_loader = loaded_package->IsCustomLoader();
-    const bool should_overlay = package_is_overlay || package_is_loader;
+    type_flags |= type_spec->GetFlagsForEntryIndex(entry_idx);
 
     if (use_fast_path) {
       const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
@@ -511,25 +631,15 @@
         // configurations that do NOT match have been filtered-out.
         if (best_config == nullptr) {
           resolution_type = Resolution::Step::Type::INITIAL;
-        } else if (this_config.isBetterThan(*best_config, desired_config)) {
-          if (package_is_loader) {
-            resolution_type = Resolution::Step::Type::BETTER_MATCH_LOADER;
-          } else {
-            resolution_type = Resolution::Step::Type::BETTER_MATCH;
-          }
-        } else if (should_overlay && this_config.compare(*best_config) == 0) {
-          if (package_is_loader) {
-            resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
-          } else if (package_is_overlay) {
-            resolution_type = Resolution::Step::Type::OVERLAID;
-          }
+        } else if (this_config.isBetterThan(*best_config, &desired_config)) {
+          resolution_type = (package_is_loader) ? Resolution::Step::Type::BETTER_MATCH_LOADER
+                                                : Resolution::Step::Type::BETTER_MATCH;
+        } else if (package_is_loader && this_config.compare(*best_config) == 0) {
+          resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
         } else {
           if (resource_resolution_logging_enabled_) {
-            if (package_is_loader) {
-              resolution_type = Resolution::Step::Type::SKIPPED_LOADER;
-            } else {
-              resolution_type = Resolution::Step::Type::SKIPPED;
-            }
+            resolution_type = (package_is_loader) ? Resolution::Step::Type::SKIPPED_LOADER
+                                                  : Resolution::Step::Type::SKIPPED;
             resolution_steps.push_back(Resolution::Step{resolution_type,
                                                         this_config.toString(),
                                                         &loaded_package->GetPackageName()});
@@ -540,7 +650,7 @@
         // The configuration matches and is better than the previous selection.
         // Find the entry value if it exists for this configuration.
         const ResTable_type* type = filtered_group.types[i];
-        const uint32_t offset = LoadedPackage::GetEntryOffset(type, local_entry_idx);
+        const uint32_t offset = LoadedPackage::GetEntryOffset(type, entry_idx);
         if (offset == ResTable_type::NO_ENTRY) {
           if (resource_resolution_logging_enabled_) {
             if (package_is_loader) {
@@ -548,7 +658,7 @@
             } else {
               resolution_type = Resolution::Step::Type::NO_ENTRY;
             }
-            resolution_steps.push_back(Resolution::Step{Resolution::Step::Type::NO_ENTRY,
+            resolution_steps.push_back(Resolution::Step{resolution_type,
                                                         this_config.toString(),
                                                         &loaded_package->GetPackageName()});
           }
@@ -562,9 +672,9 @@
         best_offset = offset;
 
         if (resource_resolution_logging_enabled_) {
-          resolution_steps.push_back(Resolution::Step{resolution_type,
-                                                      this_config.toString(),
-                                                      &loaded_package->GetPackageName()});
+          last_resolution_.steps.push_back(Resolution::Step{resolution_type,
+                                                            this_config.toString(),
+                                                            &loaded_package->GetPackageName()});
         }
       }
     } else {
@@ -579,24 +689,17 @@
 
         if (!ignore_configuration) {
           this_config.copyFromDtoH((*iter)->config);
-          if (!this_config.match(*desired_config)) {
+          if (!this_config.match(desired_config)) {
             continue;
           }
 
           if (best_config == nullptr) {
             resolution_type = Resolution::Step::Type::INITIAL;
-          } else if (this_config.isBetterThan(*best_config, desired_config)) {
-            if (package_is_loader) {
-              resolution_type = Resolution::Step::Type::BETTER_MATCH_LOADER;
-            } else {
-              resolution_type = Resolution::Step::Type::BETTER_MATCH;
-            }
-          } else if (should_overlay && this_config.compare(*best_config) == 0) {
-            if (package_is_overlay) {
-              resolution_type = Resolution::Step::Type::OVERLAID;
-            } else if (package_is_loader) {
-              resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
-            }
+          } else if (this_config.isBetterThan(*best_config, &desired_config)) {
+            resolution_type = (package_is_loader) ? Resolution::Step::Type::BETTER_MATCH_LOADER
+                                                  : Resolution::Step::Type::BETTER_MATCH;
+          } else if (package_is_loader && this_config.compare(*best_config) == 0) {
+            resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
           } else {
             continue;
           }
@@ -604,7 +707,7 @@
 
         // The configuration matches and is better than the previous selection.
         // Find the entry value if it exists for this configuration.
-        const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, local_entry_idx);
+        const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, entry_idx);
         if (offset == ResTable_type::NO_ENTRY) {
           continue;
         }
@@ -622,9 +725,9 @@
         }
 
         if (resource_resolution_logging_enabled_) {
-          resolution_steps.push_back(Resolution::Step{resolution_type,
-                                                      this_config.toString(),
-                                                      &loaded_package->GetPackageName()});
+          last_resolution_.steps.push_back(Resolution::Step{resolution_type,
+                                                            this_config.toString(),
+                                                            &loaded_package->GetPackageName()});
         }
       }
     }
@@ -639,38 +742,30 @@
     return kInvalidCookie;
   }
 
-  out_entry->entry = best_entry;
+  out_entry->entry = ResTable_entry_handle::unmanaged(best_entry);
   out_entry->config = *best_config;
   out_entry->type_flags = type_flags;
+  out_entry->package_name = &best_package->GetPackageName();
   out_entry->type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
   out_entry->entry_string_ref =
-      StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
-  out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
-
-  if (resource_resolution_logging_enabled_) {
-    last_resolution.resid = resid;
-    last_resolution.cookie = best_cookie;
-    last_resolution.steps = resolution_steps;
-
-    // Cache only the type/entry refs since that's all that's needed to build name
-    last_resolution.type_string_ref =
-        StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
-    last_resolution.entry_string_ref =
-        StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
-  }
+          StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
+  out_entry->dynamic_ref_table = package_group.dynamic_ref_table.get();
 
   return best_cookie;
 }
 
+void AssetManager2::ResetResourceResolution() const {
+  last_resolution_.cookie = kInvalidCookie;
+  last_resolution_.resid = 0;
+  last_resolution_.steps.clear();
+  last_resolution_.type_string_ref = StringPoolRef();
+  last_resolution_.entry_string_ref = StringPoolRef();
+}
+
 void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) {
   resource_resolution_logging_enabled_ = enabled;
-
   if (!enabled) {
-    last_resolution.cookie = kInvalidCookie;
-    last_resolution.resid = 0;
-    last_resolution.steps.clear();
-    last_resolution.type_string_ref = StringPoolRef();
-    last_resolution.entry_string_ref = StringPoolRef();
+    ResetResourceResolution();
   }
 }
 
@@ -680,24 +775,24 @@
     return std::string();
   }
 
-  auto cookie = last_resolution.cookie;
+  auto cookie = last_resolution_.cookie;
   if (cookie == kInvalidCookie) {
     LOG(ERROR) << "AssetManager hasn't resolved a resource to read resolution path.";
     return std::string();
   }
 
-  uint32_t resid = last_resolution.resid;
-  std::vector<Resolution::Step>& steps = last_resolution.steps;
+  uint32_t resid = last_resolution_.resid;
+  std::vector<Resolution::Step>& steps = last_resolution_.steps;
 
   ResourceName resource_name;
   std::string resource_name_string;
 
   const LoadedPackage* package =
-      apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
+          apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
 
   if (package != nullptr) {
-    ToResourceName(last_resolution.type_string_ref,
-                   last_resolution.entry_string_ref,
+    ToResourceName(last_resolution_.type_string_ref,
+                   last_resolution_.entry_string_ref,
                    package->GetPackageName(),
                    &resource_name);
     resource_name_string = ToFormattedResourceString(&resource_name);
@@ -762,25 +857,9 @@
     return false;
   }
 
-  const uint8_t package_idx = package_ids_[get_package_id(resid)];
-  if (package_idx == 0xff) {
-    LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.",
-                                     get_package_id(resid), resid);
-    return false;
-  }
-
-  const PackageGroup& package_group = package_groups_[package_idx];
-  auto cookie_iter = std::find(package_group.cookies_.begin(),
-                               package_group.cookies_.end(), cookie);
-  if (cookie_iter == package_group.cookies_.end()) {
-    return false;
-  }
-
-  long package_pos = std::distance(package_group.cookies_.begin(), cookie_iter);
-  const LoadedPackage* package = package_group.packages_[package_pos].loaded_package_;
   return ToResourceName(entry.type_string_ref,
                         entry.entry_string_ref,
-                        package->GetPackageName(),
+                        *entry.package_name,
                         out_name);
 }
 
@@ -807,7 +886,8 @@
     return kInvalidCookie;
   }
 
-  if (dtohs(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) {
+  const ResTable_entry* table_entry = *entry.entry;
+  if (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) {
     if (!may_be_bag) {
       LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
       return kInvalidCookie;
@@ -822,7 +902,7 @@
   }
 
   const Res_value* device_value = reinterpret_cast<const Res_value*>(
-      reinterpret_cast<const uint8_t*>(entry.entry) + dtohs(entry.entry->size));
+      reinterpret_cast<const uint8_t*>(table_entry) + dtohs(table_entry->size));
   out_value->copyFrom_dtoh(*device_value);
 
   // Convert the package ID to the runtime assigned package ID.
@@ -903,13 +983,14 @@
   // Check that the size of the entry header is at least as big as
   // the desired ResTable_map_entry. Also verify that the entry
   // was intended to be a map.
-  if (dtohs(entry.entry->size) < sizeof(ResTable_map_entry) ||
-      (dtohs(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) {
+  const ResTable_entry* table_entry = *entry.entry;
+  if (dtohs(table_entry->size) < sizeof(ResTable_map_entry) ||
+      (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) {
     // Not a bag, nothing to do.
     return nullptr;
   }
 
-  const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(entry.entry);
+  const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(table_entry);
   const ResTable_map* map_entry =
       reinterpret_cast<const ResTable_map*>(reinterpret_cast<const uint8_t*>(map) + map->size);
   const ResTable_map* const map_entry_end = map_entry + dtohl(map->count);
@@ -1134,7 +1215,7 @@
       }
 
       if (resid != 0u) {
-        return fix_package_id(resid, package_group.dynamic_ref_table.mAssignedPackageId);
+        return fix_package_id(resid, package_group.dynamic_ref_table->mAssignedPackageId);
       }
     }
   }
@@ -1191,7 +1272,7 @@
   for (auto& package_group : package_groups_) {
     for (auto& package2 : package_group.packages_) {
       if (package2.loaded_package_ == package) {
-        return package_group.dynamic_ref_table.mAssignedPackageId;
+        return package_group.dynamic_ref_table->mAssignedPackageId;
       }
     }
   }
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 7c1ee5c..2b69c92 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -20,6 +20,8 @@
 
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/Util.h"
 #include "utils/ByteOrder.h"
 #include "utils/Trace.h"
 
@@ -29,40 +31,124 @@
 #endif
 #endif
 
-#include "androidfw/ResourceTypes.h"
-
 using ::android::base::StringPrintf;
 
 namespace android {
 
-constexpr static inline bool is_valid_package_id(uint16_t id) {
-  return id != 0 && id <= 255;
+static bool compare_target_entries(const Idmap_target_entry &e1, const uint32_t target_id) {
+  return dtohl(e1.target_id) < target_id;
 }
 
-constexpr static inline bool is_valid_type_id(uint16_t id) {
-  // Type IDs and package IDs have the same constraints in the IDMAP.
-  return is_valid_package_id(id);
+static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
+  return dtohl(e1.overlay_id) < overlay_id;
 }
 
-bool LoadedIdmap::Lookup(const IdmapEntry_header* header, uint16_t input_entry_id,
-                         uint16_t* output_entry_id) {
-  if (input_entry_id < dtohs(header->entry_id_offset)) {
-    // After applying the offset, the entry is not present.
-    return false;
+OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
+                                     : data_header_(loaded_idmap->data_header_),
+                                       idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
+
+OverlayStringPool::~OverlayStringPool() {
+  uninit();
+}
+
+const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
+  const size_t offset = dtohl(data_header_->string_pool_index_offset);
+  if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+    return idmap_string_pool_->stringAt(idx - offset, outLen);
   }
 
-  input_entry_id -= dtohs(header->entry_id_offset);
-  if (input_entry_id >= dtohs(header->entry_count)) {
-    // The entry is not present.
-    return false;
+  return ResStringPool::stringAt(idx, outLen);
+}
+
+const char* OverlayStringPool::string8At(size_t idx, size_t* outLen) const {
+  const size_t offset = dtohl(data_header_->string_pool_index_offset);
+  if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+    return idmap_string_pool_->string8At(idx - offset, outLen);
   }
 
-  uint32_t result = dtohl(header->entries[input_entry_id]);
-  if (result == 0xffffffffu) {
-    return false;
+  return ResStringPool::string8At(idx, outLen);
+}
+
+OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
+                                               const Idmap_overlay_entry* entries,
+                                               uint8_t target_assigned_package_id)
+    : data_header_(data_header),
+      entries_(entries),
+      target_assigned_package_id_(target_assigned_package_id) { };
+
+status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
+  const Idmap_overlay_entry* first_entry = entries_;
+  const Idmap_overlay_entry* end_entry = entries_ + dtohl(data_header_->overlay_entry_count);
+  auto entry = std::lower_bound(first_entry, end_entry, *resId, compare_overlay_entries);
+
+  if (entry == end_entry || dtohl(entry->overlay_id) != *resId) {
+    // A mapping for the target resource id could not be found.
+    return DynamicRefTable::lookupResourceId(resId);
   }
-  *output_entry_id = static_cast<uint16_t>(result);
-  return true;
+
+  *resId = (0x00FFFFFFU & dtohl(entry->target_id))
+      | (((uint32_t) target_assigned_package_id_) << 24);
+  return NO_ERROR;
+}
+
+status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) const {
+  return DynamicRefTable::lookupResourceId(resId);
+}
+
+IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
+                         const Idmap_target_entry* entries,
+                         uint8_t target_assigned_package_id,
+                         const OverlayDynamicRefTable* overlay_ref_table)
+    : data_header_(data_header),
+      entries_(entries),
+      target_assigned_package_id_(target_assigned_package_id),
+      overlay_ref_table_(overlay_ref_table) { };
+
+IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
+  if ((target_res_id >> 24) != target_assigned_package_id_) {
+    // The resource id must have the same package id as the target package.
+    return {};
+  }
+
+  // The resource ids encoded within the idmap are build-time resource ids.
+  target_res_id = (0x00FFFFFFU & target_res_id)
+      | (((uint32_t) data_header_->target_package_id) << 24);
+
+  const Idmap_target_entry* first_entry = entries_;
+  const Idmap_target_entry* end_entry = entries_ + dtohl(data_header_->target_entry_count);
+  auto entry = std::lower_bound(first_entry, end_entry, target_res_id, compare_target_entries);
+
+  if (entry == end_entry || dtohl(entry->target_id) != target_res_id) {
+    // A mapping for the target resource id could not be found.
+    return {};
+  }
+
+  // A reference should be treated as an alias of the resource. Instead of returning the table
+  // entry, return the alias resource id to look up. The alias resource might not reside within the
+  // overlay package, so the resource id must be fixed with the dynamic reference table of the
+  // overlay before returning.
+  if (entry->type == Res_value::TYPE_REFERENCE
+      || entry->type == Res_value::TYPE_DYNAMIC_REFERENCE) {
+    uint32_t overlay_resource_id = dtohl(entry->value);
+
+    // Lookup the resource without rewriting the overlay resource id back to the target resource id
+    // being looked up.
+    overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id);
+    return Result(overlay_resource_id);
+  }
+
+  // Copy the type and value into the ResTable_entry structure needed by asset manager.
+  uint16_t malloc_size = sizeof(ResTable_entry) + sizeof(Res_value);
+  auto table_entry = reinterpret_cast<ResTable_entry*>(malloc(malloc_size));
+  memset(table_entry, 0, malloc_size);
+  table_entry->size = htods(sizeof(ResTable_entry));
+
+  auto table_value = reinterpret_cast<Res_value*>(reinterpret_cast<uint8_t*>(table_entry)
+      + sizeof(ResTable_entry));
+  table_value->dataType = entry->type;
+  table_value->data = entry->value;
+
+  return Result(ResTable_entry_handle::managed(table_entry));
 }
 
 static bool is_word_aligned(const void* data) {
@@ -95,24 +181,26 @@
     return false;
   }
 
-  if (!is_valid_package_id(dtohs(header->target_package_id))) {
-    LOG(ERROR) << StringPrintf("Target package ID in Idmap is invalid: 0x%02x",
-                               dtohs(header->target_package_id));
-    return false;
-  }
-
-  if (dtohs(header->type_count) > 255) {
-    LOG(ERROR) << StringPrintf("Idmap has too many type mappings (was %d, max 255)",
-                               (int)dtohs(header->type_count));
-    return false;
-  }
   return true;
 }
 
-LoadedIdmap::LoadedIdmap(const Idmap_header* header) : header_(header) {
+LoadedIdmap::LoadedIdmap(const Idmap_header* header,
+                         const Idmap_data_header* data_header,
+                         const Idmap_target_entry* target_entries,
+                         const Idmap_overlay_entry* overlay_entries,
+                         ResStringPool* string_pool) : header_(header),
+                                                       data_header_(data_header),
+                                                       target_entries_(target_entries),
+                                                       overlay_entries_(overlay_entries),
+                                                       string_pool_(string_pool) {
+
   size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
                           arraysize(header_->overlay_path));
   overlay_apk_path_.assign(reinterpret_cast<const char*>(header_->overlay_path), length);
+
+  length = strnlen(reinterpret_cast<const char*>(header_->target_path),
+                          arraysize(header_->target_path));
+  target_apk_path_.assign(reinterpret_cast<const char*>(header_->target_path), length);
 }
 
 std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_data) {
@@ -121,70 +209,67 @@
     return {};
   }
 
-  const Idmap_header* header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
-
-  // Can't use make_unique because LoadedImpl constructor is private.
-  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(new LoadedIdmap(header));
-
+  auto header = reinterpret_cast<const Idmap_header*>(idmap_data.data());
   const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data()) + sizeof(*header);
   size_t data_size = idmap_data.size() - sizeof(*header);
 
-  size_t type_maps_encountered = 0u;
-  while (data_size >= sizeof(IdmapEntry_header)) {
-    if (!is_word_aligned(data_ptr)) {
-      LOG(ERROR) << "Type mapping in Idmap is not word aligned";
-      return {};
-    }
+  // Currently idmap2 can only generate one data block.
+  auto data_header = reinterpret_cast<const Idmap_data_header*>(data_ptr);
+  data_ptr += sizeof(*data_header);
+  data_size -= sizeof(*data_header);
 
-    // Validate the type IDs.
-    const IdmapEntry_header* entry_header = reinterpret_cast<const IdmapEntry_header*>(data_ptr);
-    if (!is_valid_type_id(dtohs(entry_header->target_type_id)) || !is_valid_type_id(dtohs(entry_header->overlay_type_id))) {
-      LOG(ERROR) << StringPrintf("Invalid type map (0x%02x -> 0x%02x)",
-                                 dtohs(entry_header->target_type_id),
-                                 dtohs(entry_header->overlay_type_id));
-      return {};
-    }
-
-    // Make sure there is enough space for the entries declared in the header.
-    if ((data_size - sizeof(*entry_header)) / sizeof(uint32_t) <
-        static_cast<size_t>(dtohs(entry_header->entry_count))) {
-      LOG(ERROR) << StringPrintf("Idmap too small for the number of entries (%d)",
-                                 (int)dtohs(entry_header->entry_count));
-      return {};
-    }
-
-    // Only add a non-empty overlay.
-    if (dtohs(entry_header->entry_count != 0)) {
-      loaded_idmap->type_map_[static_cast<uint8_t>(dtohs(entry_header->overlay_type_id))] =
-          entry_header;
-    }
-
-    const size_t entry_size_bytes =
-        sizeof(*entry_header) + (dtohs(entry_header->entry_count) * sizeof(uint32_t));
-    data_ptr += entry_size_bytes;
-    data_size -= entry_size_bytes;
-    type_maps_encountered++;
-  }
-
-  // Verify that we parsed all the type maps.
-  if (type_maps_encountered != static_cast<size_t>(dtohs(header->type_count))) {
-    LOG(ERROR) << "Parsed " << type_maps_encountered << " type maps but expected "
-               << (int)dtohs(header->type_count);
+  // Make sure there is enough space for the target entries declared in the header.
+  const auto target_entries = reinterpret_cast<const Idmap_target_entry*>(data_ptr);
+  if (data_size / sizeof(Idmap_target_entry) <
+      static_cast<size_t>(dtohl(data_header->target_entry_count))) {
+    LOG(ERROR) << StringPrintf("Idmap too small for the number of target entries (%d)",
+                               (int)dtohl(data_header->target_entry_count));
     return {};
   }
-  return std::move(loaded_idmap);
-}
 
-uint8_t LoadedIdmap::TargetPackageId() const {
-  return static_cast<uint8_t>(dtohs(header_->target_package_id));
-}
+  // Advance the data pointer past the target entries.
+  const size_t target_entry_size_bytes =
+      (dtohl(data_header->target_entry_count) * sizeof(Idmap_target_entry));
+  data_ptr += target_entry_size_bytes;
+  data_size -= target_entry_size_bytes;
 
-const IdmapEntry_header* LoadedIdmap::GetEntryMapForType(uint8_t type_id) const {
-  auto iter = type_map_.find(type_id);
-  if (iter != type_map_.end()) {
-    return iter->second;
+  // Make sure there is enough space for the overlay entries declared in the header.
+  const auto overlay_entries = reinterpret_cast<const Idmap_overlay_entry*>(data_ptr);
+  if (data_size / sizeof(Idmap_overlay_entry) <
+      static_cast<size_t>(dtohl(data_header->overlay_entry_count))) {
+    LOG(ERROR) << StringPrintf("Idmap too small for the number of overlay entries (%d)",
+                               (int)dtohl(data_header->overlay_entry_count));
+    return {};
   }
-  return nullptr;
+
+  // Advance the data pointer past the target entries.
+  const size_t overlay_entry_size_bytes =
+      (dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry));
+  data_ptr += overlay_entry_size_bytes;
+  data_size -= overlay_entry_size_bytes;
+
+  // Read the idmap string pool that holds the value of inline string entries.
+  if (data_size < dtohl(data_header->string_pool_length)) {
+    LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)",
+                               (int)dtohl(data_header->string_pool_length));
+    return {};
+  }
+
+  auto idmap_string_pool = util::make_unique<ResStringPool>();
+  if (dtohl(data_header->string_pool_length) > 0) {
+    status_t err = idmap_string_pool->setTo(data_ptr, dtohl(data_header->string_pool_length));
+    if (err != NO_ERROR) {
+      LOG(ERROR) << "idmap string pool corrupt.";
+      return {};
+    }
+  }
+
+   // Can't use make_unique because LoadedImpl constructor is private.
+  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
+      new LoadedIdmap(header, data_header, target_entries, overlay_entries,
+                      idmap_string_pool.release()));
+
+  return std::move(loaded_idmap);
 }
 
 }  // namespace android
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 882dc0d..c896241 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -51,9 +51,8 @@
 // the Type structs.
 class TypeSpecPtrBuilder {
  public:
-  explicit TypeSpecPtrBuilder(const ResTable_typeSpec* header,
-                              const IdmapEntry_header* idmap_header)
-      : header_(header), idmap_header_(idmap_header) {
+  explicit TypeSpecPtrBuilder(const ResTable_typeSpec* header)
+      : header_(header) {
   }
 
   void AddType(const ResTable_type* type) {
@@ -70,7 +69,6 @@
     TypeSpec* type_spec =
         (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(ElementType)));
     type_spec->type_spec = header_;
-    type_spec->idmap_entries = idmap_header_;
     type_spec->type_count = types_.size();
     memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(ElementType));
     return TypeSpecPtr(type_spec);
@@ -80,7 +78,6 @@
   DISALLOW_COPY_AND_ASSIGN(TypeSpecPtrBuilder);
 
   const ResTable_typeSpec* header_;
-  const IdmapEntry_header* idmap_header_;
   std::vector<const ResTable_type*> types_;
 };
 
@@ -400,7 +397,6 @@
 }
 
 std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
-                                                         const LoadedIdmap* loaded_idmap,
                                                          bool system,
                                                          bool load_as_shared_library,
                                                          bool for_loader) {
@@ -426,12 +422,6 @@
     loaded_package->dynamic_ = true;
   }
 
-  if (loaded_idmap != nullptr) {
-    // This is an overlay and so it needs to pretend to be the target package.
-    loaded_package->package_id_ = loaded_idmap->TargetPackageId();
-    loaded_package->overlay_ = true;
-  }
-
   if (for_loader) {
     loaded_package->custom_loader_ = true;
   }
@@ -517,16 +507,9 @@
           return {};
         }
 
-        // If this is an overlay, associate the mapping of this type to the target type
-        // from the IDMAP.
-        const IdmapEntry_header* idmap_entry_header = nullptr;
-        if (loaded_idmap != nullptr) {
-          idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id);
-        }
-
         std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
         if (builder_ptr == nullptr) {
-          builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
+          builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec);
           loaded_package->resource_ids_.set(type_spec->id, entry_count);
         } else {
           LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
@@ -687,15 +670,7 @@
       return {};
     }
 
-    // We only add the type to the package if there is no IDMAP, or if the type is
-    // overlaying something.
-    if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) {
-      // If this is an overlay, insert it at the target type ID.
-      if (type_spec_ptr->idmap_entries != nullptr) {
-        type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1;
-      }
-      loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
-    }
+    loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
   }
 
   return std::move(loaded_package);
@@ -709,6 +684,10 @@
     return false;
   }
 
+  if (loaded_idmap != nullptr) {
+    global_string_pool_ = util::make_unique<OverlayStringPool>(loaded_idmap);
+  }
+
   const size_t package_count = dtohl(header->packageCount);
   size_t packages_seen = 0;
 
@@ -720,9 +699,9 @@
     switch (child_chunk.type()) {
       case RES_STRING_POOL_TYPE:
         // Only use the first string pool. Ignore others.
-        if (global_string_pool_.getError() == NO_INIT) {
-          status_t err = global_string_pool_.setTo(child_chunk.header<ResStringPool_header>(),
-                                                   child_chunk.size());
+        if (global_string_pool_->getError() == NO_INIT) {
+          status_t err = global_string_pool_->setTo(child_chunk.header<ResStringPool_header>(),
+                                                    child_chunk.size());
           if (err != NO_ERROR) {
             LOG(ERROR) << "RES_STRING_POOL_TYPE corrupt.";
             return false;
@@ -741,11 +720,7 @@
         packages_seen++;
 
         std::unique_ptr<const LoadedPackage> loaded_package =
-            LoadedPackage::Load(child_chunk,
-                                loaded_idmap,
-                                system_,
-                                load_as_shared_library,
-                                for_loader);
+            LoadedPackage::Load(child_chunk, system_, load_as_shared_library, for_loader);
         if (!loaded_package) {
           return false;
         }
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3fe2c5b..4d7e5df 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1363,11 +1363,10 @@
                 (((const uint8_t*)tag)
                  + dtohs(tag->attributeStart)
                  + (dtohs(tag->attributeSize)*idx));
-            if (attr->typedValue.dataType != Res_value::TYPE_DYNAMIC_REFERENCE ||
-                    mTree.mDynamicRefTable == NULL) {
+            if (mTree.mDynamicRefTable == NULL ||
+                    !mTree.mDynamicRefTable->requiresLookup(&attr->typedValue)) {
                 return dtohl(attr->typedValue.data);
             }
-
             uint32_t data = dtohl(attr->typedValue.data);
             if (mTree.mDynamicRefTable->lookupResourceId(&data) == NO_ERROR) {
                 return data;
@@ -1613,10 +1612,9 @@
 
 static volatile int32_t gCount = 0;
 
-ResXMLTree::ResXMLTree(const DynamicRefTable* dynamicRefTable)
+ResXMLTree::ResXMLTree(std::shared_ptr<const DynamicRefTable> dynamicRefTable)
     : ResXMLParser(*this)
-    , mDynamicRefTable((dynamicRefTable != nullptr) ? dynamicRefTable->clone()
-                                                    : std::unique_ptr<DynamicRefTable>(nullptr))
+    , mDynamicRefTable(std::move(dynamicRefTable))
     , mError(NO_INIT), mOwnedData(NULL)
 {
     if (kDebugResXMLTree) {
@@ -1627,7 +1625,7 @@
 
 ResXMLTree::ResXMLTree()
     : ResXMLParser(*this)
-    , mDynamicRefTable(std::unique_ptr<DynamicRefTable>(nullptr))
+    , mDynamicRefTable(nullptr)
     , mError(NO_INIT), mOwnedData(NULL)
 {
     if (kDebugResXMLTree) {
@@ -4789,7 +4787,7 @@
         packageGroup->clearBagCache();
 
         // Find which configurations match the set of parameters. This allows for a much
-        // faster lookup in getEntry() if the set of values is narrowed down.
+        // faster lookup in Lookup() if the set of values is narrowed down.
         for (size_t t = 0; t < packageGroup->types.size(); t++) {
             if (packageGroup->types[t].isEmpty()) {
                 continue;
@@ -6897,13 +6895,6 @@
     mLookupTable[SYS_PACKAGE_ID] = SYS_PACKAGE_ID;
 }
 
-std::unique_ptr<DynamicRefTable> DynamicRefTable::clone() const {
-  std::unique_ptr<DynamicRefTable> clone = std::unique_ptr<DynamicRefTable>(
-      new DynamicRefTable(mAssignedPackageId, mAppAsLib));
-  clone->addMappings(*this);
-  return clone;
-}
-
 status_t DynamicRefTable::load(const ResTable_lib_header* const header)
 {
     const uint32_t entryCount = dtohl(header->count);
@@ -7020,21 +7011,29 @@
     return NO_ERROR;
 }
 
+bool DynamicRefTable::requiresLookup(const Res_value* value) const {
+    // Only resolve non-dynamic references and attributes if the package is loaded as a
+    // library or if a shared library is attempting to retrieve its own resource
+    if ((value->dataType == Res_value::TYPE_REFERENCE ||
+         value->dataType == Res_value::TYPE_ATTRIBUTE) &&
+        (mAppAsLib || (Res_GETPACKAGE(value->data) + 1) == 0)) {
+        return true;
+    }
+    return value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE ||
+           value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE;
+}
+
 status_t DynamicRefTable::lookupResourceValue(Res_value* value) const {
+    if (!requiresLookup(value)) {
+      return NO_ERROR;
+    }
+
     uint8_t resolvedType = Res_value::TYPE_REFERENCE;
     switch (value->dataType) {
         case Res_value::TYPE_ATTRIBUTE:
             resolvedType = Res_value::TYPE_ATTRIBUTE;
             FALLTHROUGH_INTENDED;
         case Res_value::TYPE_REFERENCE:
-            // Only resolve non-dynamic references and attributes if the package is loaded as a
-            // library or if a shared library is attempting to retrieve its own resource
-            if (!(mAppAsLib || (Res_GETPACKAGE(value->data) + 1) == 0)) {
-                return NO_ERROR;
-            }
-
-        // If the package is loaded as shared library, the resource reference
-        // also need to be fixed.
         break;
         case Res_value::TYPE_DYNAMIC_ATTRIBUTE:
             resolvedType = Res_value::TYPE_ATTRIBUTE;
diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING
index a58b47f..d1a6a5c 100644
--- a/libs/androidfw/TEST_MAPPING
+++ b/libs/androidfw/TEST_MAPPING
@@ -3,6 +3,9 @@
     {
       "name": "libandroidfw_tests",
       "host": true
+    },
+    {
+      "name": "FrameworksResourceLoaderTests"
     }
   ]
 }
\ No newline at end of file
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 625b6820..2047287 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -24,6 +24,7 @@
 #include "android-base/unique_fd.h"
 
 #include "androidfw/Asset.h"
+#include "androidfw/Idmap.h"
 #include "androidfw/LoadedArsc.h"
 #include "androidfw/misc.h"
 
@@ -95,10 +96,18 @@
     return loaded_arsc_.get();
   }
 
+  inline const LoadedIdmap* GetLoadedIdmap() const {
+    return loaded_idmap_.get();
+  }
+
   inline bool IsOverlay() const {
     return idmap_asset_.get() != nullptr;
   }
 
+  inline bool IsLoader() const {
+    return for_loader_;
+  }
+
   bool IsUpToDate() const;
 
   // Creates an Asset from any file on the file system.
@@ -127,10 +136,11 @@
   ZipArchivePtr zip_handle_;
   const std::string path_;
   time_t last_mod_time_;
-  bool for_loader;
+  bool for_loader_;
   std::unique_ptr<Asset> resources_asset_;
   std::unique_ptr<Asset> idmap_asset_;
   std::unique_ptr<const LoadedArsc> loaded_arsc_;
+  std::unique_ptr<const LoadedIdmap> loaded_idmap_;
 };
 
 }  // namespace android
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index c7348b1..20e4023 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -122,7 +122,7 @@
 
   // Returns the DynamicRefTable for the ApkAssets represented by the cookie.
   // This may be nullptr if the APK represented by `cookie` has no resource table.
-  const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+  std::shared_ptr<const DynamicRefTable> GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
 
   // Returns a string representation of the overlayable API of a package.
   bool GetOverlayablesToString(const android::StringPiece& package_name,
@@ -236,12 +236,14 @@
                                    ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
                                    uint32_t* out_last_reference) const;
 
-  // Enables or disables resource resolution logging. Clears stored steps when
-  // disabled.
+  // Resets the resource resolution structures in preparation for the next resource retrieval.
+  void ResetResourceResolution() const;
+
+  // Enables or disables resource resolution logging. Clears stored steps when disabled.
   void SetResourceResolutionLoggingEnabled(bool enabled);
 
-  // Returns formatted log of last resource resolution path, or empty if no
-  // resource has been resolved yet.
+  // Returns formatted log of last resource resolution path, or empty if no resource has been
+  // resolved yet.
   std::string GetLastResourceResolution() const;
 
   const std::vector<uint32_t> GetBagResIdStack(uint32_t resid);
@@ -264,7 +266,7 @@
   void ForEachPackage(const std::function<bool(const std::string&, uint8_t)> func) const {
     for (const PackageGroup& package_group : package_groups_) {
       if (!func(package_group.packages_.front().loaded_package_->GetPackageName(),
-           package_group.dynamic_ref_table.mAssignedPackageId)) {
+           package_group.dynamic_ref_table->mAssignedPackageId)) {
         return;
       }
     }
@@ -275,6 +277,50 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(AssetManager2);
 
+  // A collection of configurations and their associated ResTable_type that match the current
+  // AssetManager configuration.
+  struct FilteredConfigGroup {
+      std::vector<ResTable_config> configurations;
+      std::vector<const ResTable_type*> types;
+  };
+
+  // Represents an single package.
+  struct ConfiguredPackage {
+      // A pointer to the immutable, loaded package info.
+      const LoadedPackage* loaded_package_;
+
+      // A mutable AssetManager-specific list of configurations that match the AssetManager's
+      // current configuration. This is used as an optimization to avoid checking every single
+      // candidate configuration when looking up resources.
+      ByteBucketArray<FilteredConfigGroup> filtered_configs_;
+  };
+
+  // Represents a Runtime Resource Overlay that overlays resources in the logical package.
+  struct ConfiguredOverlay {
+      // The set of package groups that overlay this package group.
+      IdmapResMap overlay_res_maps_;
+
+      // The cookie of the overlay assets.
+      ApkAssetsCookie cookie;
+  };
+
+  // Represents a logical package, which can be made up of many individual packages. Each package
+  // in a PackageGroup shares the same package name and package ID.
+  struct PackageGroup {
+      // The set of packages that make-up this group.
+      std::vector<ConfiguredPackage> packages_;
+
+      // The cookies associated with each package in the group. They share the same order as
+      // packages_.
+      std::vector<ApkAssetsCookie> cookies_;
+
+      // Runtime Resource Overlays that overlay resources in this package group.
+      std::vector<ConfiguredOverlay> overlays_;
+
+      // A library reference table that contains build-package ID to runtime-package ID mappings.
+      std::shared_ptr<DynamicRefTable> dynamic_ref_table = std::make_shared<DynamicRefTable>();
+  };
+
   // Finds the best entry for `resid` from the set of ApkAssets. The entry can be a simple
   // Res_value, or a complex map/bag type. If successful, it is available in `out_entry`.
   // Returns kInvalidCookie on failure. Otherwise, the return value is the cookie associated with
@@ -295,6 +341,11 @@
   ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
                             bool ignore_configuration, FindEntryResult* out_entry) const;
 
+  ApkAssetsCookie FindEntryInternal(const PackageGroup& package_group, uint8_t type_idx,
+                                    uint16_t entry_idx, const ResTable_config& desired_config,
+                                    bool /*stop_at_first_match*/,
+                                    bool ignore_configuration, FindEntryResult* out_entry) const;
+
   // Assigns package IDs to all shared library ApkAssets.
   // Should be called whenever the ApkAssets are changed.
   void BuildDynamicRefTable();
@@ -307,6 +358,9 @@
   // This should always be called when mutating the AssetManager's configuration or ApkAssets set.
   void RebuildFilterList(bool filter_incompatible_configs = true);
 
+  // Retrieves the APK paths of overlays that overlay non-system packages.
+  std::set<std::string> GetNonSystemOverlayPaths() const;
+
   // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
   // been seen while traversing bag parents.
   const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids);
@@ -318,38 +372,6 @@
   // have a longer lifetime.
   std::vector<const ApkAssets*> apk_assets_;
 
-  // A collection of configurations and their associated ResTable_type that match the current
-  // AssetManager configuration.
-  struct FilteredConfigGroup {
-    std::vector<ResTable_config> configurations;
-    std::vector<const ResTable_type*> types;
-  };
-
-  // Represents an single package.
-  struct ConfiguredPackage {
-    // A pointer to the immutable, loaded package info.
-    const LoadedPackage* loaded_package_;
-
-    // A mutable AssetManager-specific list of configurations that match the AssetManager's
-    // current configuration. This is used as an optimization to avoid checking every single
-    // candidate configuration when looking up resources.
-    ByteBucketArray<FilteredConfigGroup> filtered_configs_;
-  };
-
-  // Represents a logical package, which can be made up of many individual packages. Each package
-  // in a PackageGroup shares the same package name and package ID.
-  struct PackageGroup {
-    // The set of packages that make-up this group.
-    std::vector<ConfiguredPackage> packages_;
-
-    // The cookies associated with each package in the group. They share the same order as
-    // packages_.
-    std::vector<ApkAssetsCookie> cookies_;
-
-    // A library reference table that contains build-package ID to runtime-package ID mappings.
-    DynamicRefTable dynamic_ref_table;
-  };
-
   // DynamicRefTables for shared library package resolution.
   // These are ordered according to apk_assets_. The mappings may change depending on what is
   // in apk_assets_, therefore they must be stored in the AssetManager and not in the
@@ -418,7 +440,7 @@
   };
 
   // Record of the last resolved resource's resolution path.
-  mutable Resolution last_resolution;
+  mutable Resolution last_resolution_;
 };
 
 class Theme {
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index fd02e6f..ab4c9c2 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -20,20 +20,122 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <variant>
 
 #include "android-base/macros.h"
-
 #include "androidfw/StringPiece.h"
+#include "androidfw/ResourceTypes.h"
+#include "utils/ByteOrder.h"
 
 namespace android {
 
-struct Idmap_header;
-struct IdmapEntry_header;
+class LoadedIdmap;
+class IdmapResMap;
+
+// A string pool for overlay apk assets. The string pool holds the strings of the overlay resources
+// table and additionally allows for loading strings from the idmap string pool. The idmap string
+// pool strings are offset after the end of the overlay resource table string pool entries so
+// queries for strings defined inline in the idmap do not conflict with queries for overlay
+// resource table strings.
+class OverlayStringPool : public ResStringPool {
+ public:
+  virtual ~OverlayStringPool();
+  virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
+  virtual const char* string8At(size_t idx, size_t* outLen) const;
+
+  explicit OverlayStringPool(const LoadedIdmap* loaded_idmap);
+ private:
+    const Idmap_data_header* data_header_;
+    const ResStringPool* idmap_string_pool_;
+};
+
+// A dynamic reference table for loaded overlay packages that rewrites the resource id of overlay
+// resources to the resource id of corresponding target resources.
+class OverlayDynamicRefTable : public DynamicRefTable {
+ public:
+  virtual ~OverlayDynamicRefTable() = default;
+  virtual status_t lookupResourceId(uint32_t* resId) const;
+
+ private:
+  explicit OverlayDynamicRefTable(const Idmap_data_header* data_header,
+                                  const Idmap_overlay_entry* entries,
+                                  uint8_t target_assigned_package_id);
+
+  // Rewrites a compile-time overlay resource id to the runtime resource id of corresponding target
+  // resource.
+  virtual status_t lookupResourceIdNoRewrite(uint32_t* resId) const;
+
+  const Idmap_data_header* data_header_;
+  const Idmap_overlay_entry* entries_;
+  const int8_t target_assigned_package_id_;
+
+  friend LoadedIdmap;
+  friend IdmapResMap;
+};
+
+// A mapping of target resource ids to a values or resource ids that should overlay the target.
+class IdmapResMap {
+ public:
+  // Represents the result of a idmap lookup. The result can be one of three possibillities:
+  // 1) The result is a resource id which represents the overlay resource that should act as an
+  //    alias of the target resource.
+  // 2) The result is a table entry which overlays the type and value of the target resource.
+  // 3) The result is neither and the target resource is not overlaid.
+  class Result {
+   public:
+    Result() : data_(nullptr) {};
+    explicit Result(uint32_t value) : data_(value) {};
+    explicit Result(ResTable_entry_handle&& value) : data_(value) { };
+
+    // Returns `true` if the resource is overlaid.
+    inline explicit operator bool() const {
+      return !std::get_if<nullptr_t>(&data_);
+    }
+
+    inline bool IsResourceId() const {
+      return std::get_if<uint32_t>(&data_);
+    }
+
+    inline uint32_t GetResourceId() const {
+      return *std::get_if<uint32_t>(&data_);
+    }
+
+    inline bool IsTableEntry() const {
+      return std::get_if<ResTable_entry_handle>(&data_);
+    }
+
+    inline const ResTable_entry_handle& GetTableEntry() const {
+      return *std::get_if<ResTable_entry_handle>(&data_);
+    }
+
+   private:
+      std::variant<uint32_t, nullptr_t, ResTable_entry_handle> data_;
+  };
+
+  // Looks up the value that overlays the target resource id.
+  Result Lookup(uint32_t target_res_id) const;
+
+  inline const OverlayDynamicRefTable* GetOverlayDynamicRefTable() const {
+    return overlay_ref_table_;
+  }
+
+ private:
+  explicit IdmapResMap(const Idmap_data_header* data_header,
+                       const Idmap_target_entry* entries,
+                       uint8_t target_assigned_package_id,
+                       const OverlayDynamicRefTable* overlay_ref_table);
+
+  const Idmap_data_header* data_header_;
+  const Idmap_target_entry* entries_;
+  const uint8_t target_assigned_package_id_;
+  const OverlayDynamicRefTable* overlay_ref_table_;
+
+  friend LoadedIdmap;
+};
 
 // Represents a loaded/parsed IDMAP for a Runtime Resource Overlay (RRO).
-// An RRO and its target APK have different resource IDs assigned to their resources. Overlaying
-// a resource is done by resource name. An IDMAP is a generated mapping between the resource IDs
-// of the RRO and the target APK for each resource with the same name.
+// An RRO and its target APK have different resource IDs assigned to their resources.
+// An IDMAP is a generated mapping between the resource IDs of the RRO and the target APK.
 // A LoadedIdmap can be set alongside the overlay's LoadedArsc to allow the overlay ApkAssets to
 // masquerade as the target ApkAssets resources.
 class LoadedIdmap {
@@ -41,34 +143,52 @@
   // Loads an IDMAP from a chunk of memory. Returns nullptr if the IDMAP data was malformed.
   static std::unique_ptr<const LoadedIdmap> Load(const StringPiece& idmap_data);
 
-  // Performs a lookup of the expected entry ID for the given IDMAP entry header.
-  // Returns true if the mapping exists and fills `output_entry_id` with the result.
-  static bool Lookup(const IdmapEntry_header* header, uint16_t input_entry_id,
-                     uint16_t* output_entry_id);
-
-  // Returns the package ID for which this overlay should apply.
-  uint8_t TargetPackageId() const;
-
   // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
   inline const std::string& OverlayApkPath() const {
     return overlay_apk_path_;
   }
 
-  // Returns the mapping of target entry ID to overlay entry ID for the given target type.
-  const IdmapEntry_header* GetEntryMapForType(uint8_t type_id) const;
+  // Returns the path to the RRO (Runtime Resource Overlay) APK for which this IDMAP was generated.
+  inline const std::string& TargetApkPath() const {
+    return target_apk_path_;
+  }
+
+  // Returns a mapping from target resource ids to overlay values.
+  inline const IdmapResMap GetTargetResourcesMap(
+      uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const {
+    return IdmapResMap(data_header_, target_entries_, target_assigned_package_id,
+                       overlay_ref_table);
+  }
+
+  // Returns a dynamic reference table for a loaded overlay package.
+  inline const OverlayDynamicRefTable GetOverlayDynamicRefTable(
+      uint8_t target_assigned_package_id) const {
+    return OverlayDynamicRefTable(data_header_, overlay_entries_, target_assigned_package_id);
+  }
 
  protected:
   // Exposed as protected so that tests can subclass and mock this class out.
   LoadedIdmap() = default;
 
-  const Idmap_header* header_ = nullptr;
+  const Idmap_header* header_;
+  const Idmap_data_header* data_header_;
+  const Idmap_target_entry* target_entries_;
+  const Idmap_overlay_entry* overlay_entries_;
+  const std::unique_ptr<ResStringPool> string_pool_;
+
   std::string overlay_apk_path_;
-  std::unordered_map<uint8_t, const IdmapEntry_header*> type_map_;
+  std::string target_apk_path_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
 
-  explicit LoadedIdmap(const Idmap_header* header);
+  explicit LoadedIdmap(const Idmap_header* header,
+                       const Idmap_data_header* data_header,
+                       const Idmap_target_entry* target_entries,
+                       const Idmap_overlay_entry* overlay_entries,
+                       ResStringPool* string_pool);
+
+  friend OverlayStringPool;
 };
 
 }  // namespace android
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 1a56876..ba1beaa 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -51,10 +51,6 @@
   // and under which configurations it varies.
   const ResTable_typeSpec* type_spec;
 
-  // Pointer to the mmapped data where the IDMAP mappings for this type
-  // exist. May be nullptr if no IDMAP exists.
-  const IdmapEntry_header* idmap_entries;
-
   // The number of types that follow this struct.
   // There is a type for each configuration that entries are defined for.
   size_t type_count;
@@ -135,8 +131,7 @@
     return iterator(this, resource_ids_.size() + 1, 0);
   }
 
-  static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
-                                                   const LoadedIdmap* loaded_idmap, bool system,
+  static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk, bool system,
                                                    bool load_as_shared_library,
                                                    bool load_as_custom_loader);
 
@@ -183,11 +178,6 @@
     return system_;
   }
 
-  // Returns true if this package is from an overlay ApkAssets.
-  inline bool IsOverlay() const {
-    return overlay_;
-  }
-
   // Returns true if this package is a custom loader and should behave like an overlay
   inline bool IsCustomLoader() const {
     return custom_loader_;
@@ -222,9 +212,6 @@
       const TypeSpecPtr& ptr = type_specs_[i];
       if (ptr != nullptr) {
         uint8_t type_id = ptr->type_spec->id;
-        if (ptr->idmap_entries != nullptr) {
-          type_id = ptr->idmap_entries->target_type_id;
-        }
         f(ptr.get(), type_id - 1);
       }
     }
@@ -265,7 +252,6 @@
   int type_id_offset_ = 0;
   bool dynamic_ = false;
   bool system_ = false;
-  bool overlay_ = false;
   bool custom_loader_ = false;
   bool defines_overlayable_ = false;
 
@@ -298,7 +284,7 @@
   // Returns the string pool where all string resource values
   // (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
   inline const ResStringPool* GetStringPool() const {
-    return &global_string_pool_;
+    return global_string_pool_.get();
   }
 
   // Gets a pointer to the package with the specified package ID, or nullptr if no such package
@@ -319,12 +305,8 @@
   DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
 
   LoadedArsc() = default;
-  bool LoadTable(
-      const Chunk& chunk,
-      const LoadedIdmap* loaded_idmap,
-      bool load_as_shared_library,
-      bool for_loader
-  );
+  bool LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library,
+                 bool for_loader);
 
   static std::unique_ptr<const LoadedArsc> LoadData(std::unique_ptr<LoadedArsc>& loaded_arsc,
                                                     const char* data,
@@ -333,7 +315,7 @@
                                                     bool load_as_shared_library = false,
                                                     bool for_loader = false);
 
-  ResStringPool global_string_pool_;
+  std::unique_ptr<ResStringPool> global_string_pool_ = util::make_unique<ResStringPool>();
   std::vector<std::unique_ptr<const LoadedPackage>> packages_;
   bool system_ = false;
 };
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index c8ace90..b20e657 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -39,7 +39,7 @@
 namespace android {
 
 constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
-constexpr const static uint32_t kIdmapCurrentVersion = 0x00000001u;
+constexpr const static uint32_t kIdmapCurrentVersion = 0x00000002u;
 
 /**
  * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
@@ -492,7 +492,7 @@
 public:
     ResStringPool();
     ResStringPool(const void* data, size_t size, bool copyData=false);
-    ~ResStringPool();
+    virtual ~ResStringPool();
 
     void setToEmpty();
     status_t setTo(const void* data, size_t size, bool copyData=false);
@@ -506,10 +506,10 @@
     inline const char16_t* stringAt(const ResStringPool_ref& ref, size_t* outLen) const {
         return stringAt(ref.index, outLen);
     }
-    const char16_t* stringAt(size_t idx, size_t* outLen) const;
+    virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
 
     // Note: returns null if the string pool is not UTF8.
-    const char* string8At(size_t idx, size_t* outLen) const;
+    virtual const char* string8At(size_t idx, size_t* outLen) const;
 
     // Return string whether the pool is UTF8 or UTF16.  Does not allow you
     // to distinguish null.
@@ -812,7 +812,7 @@
      * The tree stores a clone of the specified DynamicRefTable, so any changes to the original
      * DynamicRefTable will not affect this tree after instantiation.
      **/
-    explicit ResXMLTree(const DynamicRefTable* dynamicRefTable);
+    explicit ResXMLTree(std::shared_ptr<const DynamicRefTable> dynamicRefTable);
     ResXMLTree();
     ~ResXMLTree();
 
@@ -827,7 +827,7 @@
 
     status_t validateNode(const ResXMLTree_node* node) const;
 
-    std::unique_ptr<const DynamicRefTable> mDynamicRefTable;
+    std::shared_ptr<const DynamicRefTable> mDynamicRefTable;
 
     status_t                    mError;
     void*                       mOwnedData;
@@ -1584,6 +1584,50 @@
     Res_value value;
 };
 
+
+// A ResTable_entry variant that either holds an unmanaged pointer to a constant ResTable_entry or
+// holds a ResTable_entry which is tied to the lifetime of the handle.
+class ResTable_entry_handle {
+ public:
+    ResTable_entry_handle() = default;
+
+    ResTable_entry_handle(const ResTable_entry_handle& handle) {
+      entry_ = handle.entry_;
+    }
+
+    ResTable_entry_handle(ResTable_entry_handle&& handle) noexcept {
+      entry_ = handle.entry_;
+    }
+
+    inline static ResTable_entry_handle managed(ResTable_entry* entry)  {
+      return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry));
+    }
+
+    inline static ResTable_entry_handle unmanaged(const ResTable_entry* entry)  {
+      return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, [](auto /*p */){}));
+    }
+
+    inline ResTable_entry_handle& operator=(const ResTable_entry_handle& handle) noexcept {
+      entry_ = handle.entry_;
+      return *this;
+    }
+
+    inline ResTable_entry_handle& operator=(ResTable_entry_handle&& handle) noexcept {
+      entry_ = handle.entry_;
+      return *this;
+    }
+
+    inline const ResTable_entry* operator*() & {
+      return entry_.get();
+    }
+
+ private:
+    explicit ResTable_entry_handle(std::shared_ptr<const ResTable_entry> entry)
+        : entry_(std::move(entry)) { }
+
+    std::shared_ptr<const ResTable_entry> entry_;
+};
+
 /**
  * A package-id to package name mapping for any shared libraries used
  * in this resource table. The package-id's encoded in this resource
@@ -1668,7 +1712,8 @@
   uint32_t entry_count;
 };
 
-struct alignas(uint32_t) Idmap_header {
+#pragma pack(push, 1)
+struct Idmap_header {
   // Always 0x504D4449 ('IDMP')
   uint32_t magic;
 
@@ -1679,18 +1724,28 @@
 
   uint8_t target_path[256];
   uint8_t overlay_path[256];
+};
 
-  uint16_t target_package_id;
-  uint16_t type_count;
-} __attribute__((packed));
+struct Idmap_data_header {
+  uint8_t target_package_id;
+  uint8_t overlay_package_id;
+  uint32_t target_entry_count;
+  uint32_t overlay_entry_count;
+  uint32_t string_pool_index_offset;
+  uint32_t string_pool_length;
+};
 
-struct alignas(uint32_t) IdmapEntry_header {
-  uint16_t target_type_id;
-  uint16_t overlay_type_id;
-  uint16_t entry_count;
-  uint16_t entry_id_offset;
-  uint32_t entries[0];
-} __attribute__((packed));
+struct Idmap_target_entry {
+  uint32_t target_id;
+  uint8_t type;
+  uint32_t value;
+};
+
+struct Idmap_overlay_entry {
+  uint32_t overlay_id;
+  uint32_t target_id;
+};
+#pragma pack(pop)
 
 class AssetManager2;
 
@@ -1708,6 +1763,7 @@
 public:
     DynamicRefTable();
     DynamicRefTable(uint8_t packageId, bool appAsLib);
+    virtual ~DynamicRefTable() = default;
 
     // Loads an unmapped reference table from the package.
     status_t load(const ResTable_lib_header* const header);
@@ -1721,12 +1777,12 @@
 
     void addMapping(uint8_t buildPackageId, uint8_t runtimePackageId);
 
-    // Creates a new clone of the reference table
-    std::unique_ptr<DynamicRefTable> clone() const;
+    // Returns whether or not the value must be looked up.
+    bool requiresLookup(const Res_value* value) const;
 
     // Performs the actual conversion of build-time resource ID to run-time
     // resource ID.
-    status_t lookupResourceId(uint32_t* resId) const;
+    virtual status_t lookupResourceId(uint32_t* resId) const;
     status_t lookupResourceValue(Res_value* value) const;
 
     inline const KeyedVector<String16, uint8_t>& entries() const {
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index e2b9f00..0f2ee6f 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -79,39 +79,6 @@
   EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
 }
 
-TEST(ApkAssetsTest, LoadApkWithIdmap) {
-  std::string contents;
-  ResTable target_table;
-  const std::string target_path = GetTestDataPath() + "/basic/basic.apk";
-  ASSERT_TRUE(ReadFileFromZipToString(target_path, "resources.arsc", &contents));
-  ASSERT_THAT(target_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
-              Eq(NO_ERROR));
-
-  ResTable overlay_table;
-  const std::string overlay_path = GetTestDataPath() + "/overlay/overlay.apk";
-  ASSERT_TRUE(ReadFileFromZipToString(overlay_path, "resources.arsc", &contents));
-  ASSERT_THAT(overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
-              Eq(NO_ERROR));
-
-  util::unique_cptr<void> idmap_data;
-  void* temp_data;
-  size_t idmap_len;
-
-  ASSERT_THAT(target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
-                                       overlay_path.c_str(), &temp_data, &idmap_len),
-              Eq(NO_ERROR));
-  idmap_data.reset(temp_data);
-
-  TemporaryFile tf;
-  ASSERT_TRUE(base::WriteFully(tf.fd, idmap_data.get(), idmap_len));
-  close(tf.fd);
-
-  // Open something so that the destructor of TemporaryFile closes a valid fd.
-  tf.fd = open("/dev/null", O_WRONLY);
-
-  ASSERT_THAT(ApkAssets::LoadOverlay(tf.path), NotNull());
-}
-
 TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
   std::unique_ptr<const ApkAssets> loaded_apk =
       ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 1591024..b3190be 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -718,15 +718,17 @@
 
   const auto map = assetmanager.GetOverlayableMapForPackage(0x7f);
   ASSERT_NE(nullptr, map);
-  ASSERT_EQ(2, map->size());
+  ASSERT_EQ(3, map->size());
   ASSERT_EQ(map->at("OverlayableResources1"), "overlay://theme");
   ASSERT_EQ(map->at("OverlayableResources2"), "overlay://com.android.overlayable");
+  ASSERT_EQ(map->at("OverlayableResources3"), "");
 
   std::string api;
   ASSERT_TRUE(assetmanager.GetOverlayablesToString("com.android.overlayable", &api));
   ASSERT_EQ(api.find("not_overlayable"), std::string::npos);
   ASSERT_NE(api.find("resource='com.android.overlayable:string/overlayable2' overlayable='OverlayableResources1' actor='overlay://theme' policy='0x0000000a'\n"),
             std::string::npos);
+
 }
 
 }  // namespace android
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 10b83a7..b679672 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -14,114 +14,231 @@
  * limitations under the License.
  */
 
+#include "android-base/file.h"
+#include "androidfw/ApkAssets.h"
+#include "androidfw/AssetManager2.h"
 #include "androidfw/ResourceTypes.h"
 
 #include "utils/String16.h"
 #include "utils/String8.h"
 
 #include "TestHelpers.h"
-#include "data/basic/R.h"
+#include "data/overlay/R.h"
+#include "data/overlayable/R.h"
+#include "data/system/R.h"
 
-using ::com::android::basic::R;
+namespace overlay = com::android::overlay;
+namespace overlayable = com::android::overlayable;
 
 namespace android {
 
+namespace {
+
 class IdmapTest : public ::testing::Test {
  protected:
   void SetUp() override {
-    std::string contents;
-    ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc",
-                                        &contents));
-    ASSERT_EQ(NO_ERROR, target_table_.add(contents.data(), contents.size(), 0, true));
+    // Move to the test data directory so the idmap can locate the overlay APK.
+    std::string original_path = base::GetExecutableDirectory();
+    chdir(GetTestDataPath().c_str());
 
-    ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk",
-                                        "resources.arsc", &overlay_data_));
-    ResTable overlay_table;
-    ASSERT_EQ(NO_ERROR, overlay_table.add(overlay_data_.data(), overlay_data_.size()));
+    system_assets_ = ApkAssets::Load("system/system.apk");
+    ASSERT_NE(nullptr, system_assets_);
 
-    char target_name[256] = "com.android.basic";
-    ASSERT_EQ(NO_ERROR, overlay_table.createIdmap(target_table_, 0, 0, target_name, target_name,
-                                                  &data_, &data_size_));
+    overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap");
+    ASSERT_NE(nullptr, overlay_assets_);
+
+    overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
+    ASSERT_NE(nullptr, overlayable_assets_);
+    chdir(original_path.c_str());
   }
 
-  void TearDown() override {
-    ::free(data_);
-  }
-
-  ResTable target_table_;
-  std::string overlay_data_;
-  void* data_ = nullptr;
-  size_t data_size_ = 0;
+ protected:
+  std::unique_ptr<const ApkAssets> system_assets_;
+  std::unique_ptr<const ApkAssets> overlay_assets_;
+  std::unique_ptr<const ApkAssets> overlayable_assets_;
 };
 
-TEST_F(IdmapTest, CanLoadIdmap) {
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
+std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const Res_value& value,
+                                   ApkAssetsCookie cookie) {
+  auto assets = asset_manager.GetApkAssets();
+  const ResStringPool* string_pool = assets[cookie]->GetLoadedArsc()->GetStringPool();
+  return GetStringFromPool(string_pool, value.data);
+}
+
 }
 
 TEST_F(IdmapTest, OverlayOverridesResourceValue) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
   Res_value val;
-  ssize_t block = target_table_.getResource(R::string::test2, &val, false);
-  ASSERT_GE(block, 0);
-  ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
-  const ResStringPool* pool = target_table_.getTableStringBlock(block);
-  ASSERT_TRUE(pool != NULL);
-  ASSERT_LT(val.data, pool->size());
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable5,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Overlay One");
+}
 
-  size_t str_len;
-  const char16_t* target_str16 = pool->stringAt(val.data, &str_len);
-  ASSERT_TRUE(target_str16 != NULL);
-  ASSERT_EQ(String16("test2"), String16(target_str16, str_len));
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable10,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 0U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "yes");
+}
 
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable8,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(val.data, (overlay::R::string::internal & 0x00ffffff) | (0x02 << 24));
+}
 
-  ssize_t new_block = target_table_.getResource(R::string::test2, &val, false);
-  ASSERT_GE(new_block, 0);
-  ASSERT_NE(block, new_block);
-  ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
-  pool = target_table_.getTableStringBlock(new_block);
-  ASSERT_TRUE(pool != NULL);
-  ASSERT_LT(val.data, pool->size());
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::integer::config_integer,
+                                                  false /* may_be_bag */,
+                                                  0 /* density_override */, &val, &config,
+                                                  &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_INT_DEC);
+  ASSERT_EQ(val.data, 42);
+}
 
-  target_str16 = pool->stringAt(val.data, &str_len);
-  ASSERT_TRUE(target_str16 != NULL);
-  ASSERT_EQ(String16("test2-overlay"), String16(target_str16, str_len));
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
+                                                  false /* may_be_bag */,
+                                                  0 /* density_override */, &val, &config,
+                                                  &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Hardcoded string");
+}
+
+TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable9,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(val.data, overlayable::R::string::overlayable7);
+}
+
+TEST_F(IdmapTest, OverlayOverridesXmlParser) {
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
+  Res_value val;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::layout::hello_view,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  ASSERT_EQ(cookie, 2U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "res/layout/hello_view.xml");
+
+  auto asset = asset_manager.OpenNonAsset("res/layout/hello_view.xml", cookie,
+                                          Asset::ACCESS_RANDOM);
+  auto dynamic_ref_table = asset_manager.GetDynamicRefTableForCookie(cookie);
+  auto xml_tree = util::make_unique<ResXMLTree>(std::move(dynamic_ref_table));
+  status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), false);
+  ASSERT_EQ(err, NO_ERROR);
+
+  while (xml_tree->next() != ResXMLParser::START_TAG) { }
+
+  // The resource id of @id/hello_view should be rewritten to the resource id/hello_view within the
+  // target.
+  ASSERT_EQ(xml_tree->getAttributeNameResID(0), 0x010100d0 /* android:attr/id */);
+  ASSERT_EQ(xml_tree->getAttributeDataType(0), Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(xml_tree->getAttributeData(0), overlayable::R::id::hello_view);
+
+  // The resource id of @android:string/yes should not be rewritten even though it overlays
+  // string/overlayable10 in the target.
+  ASSERT_EQ(xml_tree->getAttributeNameResID(1), 0x0101014f /* android:attr/text */);
+  ASSERT_EQ(xml_tree->getAttributeDataType(1), Res_value::TYPE_REFERENCE);
+  ASSERT_EQ(xml_tree->getAttributeData(1), 0x01040013 /* android:string/yes */);
+
+  // The resource id of the attribute within the overlay should be rewritten to the resource id of
+  // the attribute in the target.
+  ASSERT_EQ(xml_tree->getAttributeNameResID(2), overlayable::R::attr::max_lines);
+  ASSERT_EQ(xml_tree->getAttributeDataType(2), Res_value::TYPE_INT_DEC);
+  ASSERT_EQ(xml_tree->getAttributeData(2), 4);
 }
 
 TEST_F(IdmapTest, OverlaidResourceHasSameName) {
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
+                              overlay_assets_.get()});
 
-  ResTable::resource_name res_name;
-  ASSERT_TRUE(target_table_.getResourceName(R::array::integerArray1, true, &res_name));
-
-  ASSERT_TRUE(res_name.package != NULL);
-  ASSERT_TRUE(res_name.type != NULL);
-  ASSERT_TRUE(res_name.name8 != NULL);
-
-  EXPECT_EQ(String16("com.android.basic"), String16(res_name.package, res_name.packageLen));
-  EXPECT_EQ(String16("array"), String16(res_name.type, res_name.typeLen));
-  EXPECT_EQ(String8("integerArray1"), String8(res_name.name8, res_name.nameLen));
+  AssetManager2::ResourceName name;
+  ASSERT_TRUE(asset_manager.GetResourceName(overlayable::R::string::overlayable9, &name));
+  ASSERT_EQ(std::string(name.package), "com.android.overlayable");
+  ASSERT_EQ(String16(name.type16), u"string");
+  ASSERT_EQ(std::string(name.entry), "overlayable9");
 }
 
-constexpr const uint32_t kNonOverlaidResourceId = 0x7fff0000u;
+TEST_F(IdmapTest, OverlayLoaderInterop) {
+  std::string contents;
+  auto loader_assets = ApkAssets::LoadArsc(GetTestDataPath() + "/loader/resources.arsc",
+                                           /* for_loader */ true);
 
-TEST_F(IdmapTest, OverlayDoesNotIncludeNonOverlaidResources) {
-  // First check that the resource we're trying to not include when overlaid is present when
-  // the overlay is loaded as a standalone APK.
-  ResTable table;
-  ASSERT_EQ(NO_ERROR, table.add(overlay_data_.data(), overlay_data_.size(), 0, true));
+  AssetManager2 asset_manager;
+  asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(),
+                              overlay_assets_.get()});
 
   Res_value val;
-  ssize_t block = table.getResource(kNonOverlaidResourceId, &val, false /*mayBeBag*/);
-  ASSERT_GE(block, 0);
-
-  // Now add the overlay and verify that the unoverlaid resource is gone.
-  ASSERT_EQ(NO_ERROR,
-            target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
-  block = target_table_.getResource(kNonOverlaidResourceId, &val, false /*mayBeBag*/);
-  ASSERT_LT(block, 0);
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
+                                                    false /* may_be_bag */,
+                                                    0 /* density_override */, &val, &config,
+                                                    &flags);
+  std::cout << asset_manager.GetLastResourceResolution();
+  ASSERT_EQ(cookie, 1U);
+  ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
+  ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader");
 }
 
 }  // namespace
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index fd57a92..82dd335 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -144,7 +144,7 @@
                                       "resources.arsc", &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
+      LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
                        true /*load_as_shared_library*/);
   ASSERT_THAT(loaded_arsc, NotNull());
 
@@ -222,67 +222,13 @@
   ASSERT_THAT(type_spec->types[0], NotNull());
 }
 
-class MockLoadedIdmap : public LoadedIdmap {
- public:
-  MockLoadedIdmap() : LoadedIdmap() {
-    local_header_.magic = kIdmapMagic;
-    local_header_.version = kIdmapCurrentVersion;
-    local_header_.target_package_id = 0x08;
-    local_header_.type_count = 1;
-    header_ = &local_header_;
-
-    entry_header = util::unique_cptr<IdmapEntry_header>(
-        (IdmapEntry_header*)::malloc(sizeof(IdmapEntry_header) + sizeof(uint32_t)));
-    entry_header->target_type_id = 0x03;
-    entry_header->overlay_type_id = 0x02;
-    entry_header->entry_id_offset = 1;
-    entry_header->entry_count = 1;
-    entry_header->entries[0] = 0x00000000u;
-    type_map_[entry_header->overlay_type_id] = entry_header.get();
-  }
-
- private:
-  Idmap_header local_header_;
-  util::unique_cptr<IdmapEntry_header> entry_header;
-};
-
-TEST(LoadedArscTest, LoadOverlay) {
-  std::string contents;
-  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
-                                      &contents));
-
-  MockLoadedIdmap loaded_idmap;
-
-  std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(contents), &loaded_idmap);
-  ASSERT_THAT(loaded_arsc, NotNull());
-
-  const LoadedPackage* package = loaded_arsc->GetPackageById(0x08u);
-  ASSERT_THAT(package, NotNull());
-
-  const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0x03u - 1);
-  ASSERT_THAT(type_spec, NotNull());
-  ASSERT_THAT(type_spec->type_count, Ge(1u));
-  ASSERT_THAT(type_spec->types[0], NotNull());
-
-  // The entry being overlaid doesn't exist at the original entry index.
-  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0001u), IsNull());
-
-  // Since this is an overlay, the actual entry ID must be mapped.
-  ASSERT_THAT(type_spec->idmap_entries, NotNull());
-  uint16_t target_entry_id = 0u;
-  ASSERT_TRUE(LoadedIdmap::Lookup(type_spec->idmap_entries, 0x0001u, &target_entry_id));
-  ASSERT_THAT(target_entry_id, Eq(0x0u));
-  ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull());
-}
-
 TEST(LoadedArscTest, LoadOverlayable) {
   std::string contents;
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlayable/overlayable.apk",
                                       "resources.arsc", &contents));
 
   std::unique_ptr<const LoadedArsc> loaded_arsc =
-      LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
+      LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
                        false /*load_as_shared_library*/);
 
   ASSERT_THAT(loaded_arsc, NotNull());
@@ -383,9 +329,10 @@
   ASSERT_EQ(std::string("com.android.overlayable"), packages[0]->GetPackageName());
 
   const auto map = packages[0]->GetOverlayableMap();
-  ASSERT_EQ(2, map.size());
+  ASSERT_EQ(3, map.size());
   ASSERT_EQ(map.at("OverlayableResources1"), "overlay://theme");
   ASSERT_EQ(map.at("OverlayableResources2"), "overlay://com.android.overlayable");
+  ASSERT_EQ(map.at("OverlayableResources3"), "");
 }
 
 TEST(LoadedArscTest, LoadCustomLoader) {
@@ -394,7 +341,6 @@
   std::unique_ptr<Asset>
       asset = ApkAssets::CreateAssetFromFile(GetTestDataPath() + "/loader/resources.arsc");
 
-  MockLoadedIdmap loaded_idmap;
   const StringPiece data(
       reinterpret_cast<const char*>(asset->getBuffer(true /*wordAligned*/)),
       asset->getLength());
@@ -404,13 +350,13 @@
   ASSERT_THAT(loaded_arsc, NotNull());
 
   const LoadedPackage* package =
-      loaded_arsc->GetPackageById(get_package_id(android::R::string::cancel));
+      loaded_arsc->GetPackageById(get_package_id(overlayable::R::string::overlayable11));
   ASSERT_THAT(package, NotNull());
-  EXPECT_THAT(package->GetPackageName(), StrEq("android"));
-  EXPECT_THAT(package->GetPackageId(), Eq(0x01));
+  EXPECT_THAT(package->GetPackageName(), StrEq("com.android.loader"));
+  EXPECT_THAT(package->GetPackageId(), Eq(0x7f));
 
-  const uint8_t type_index = get_type_id(android::R::string::cancel) - 1;
-  const uint16_t entry_index = get_entry_id(android::R::string::cancel);
+  const uint8_t type_index = get_type_id(overlayable::R::string::overlayable11) - 1;
+  const uint16_t entry_index = get_entry_id(overlayable::R::string::overlayable11);
 
   const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
   ASSERT_THAT(type_spec, NotNull());
diff --git a/libs/androidfw/tests/data/loader/AndroidManifest.xml b/libs/androidfw/tests/data/loader/AndroidManifest.xml
new file mode 100644
index 0000000..4c0bb47
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest package="com.android.loader">
+    <application>
+    </application>
+</manifest>
diff --git a/libs/androidfw/tests/data/loader/build b/libs/androidfw/tests/data/loader/build
new file mode 100755
index 0000000..457ec51
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/build
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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.
+#
+
+set -e
+
+FRAMEWORK_RES_APK=${ANDROID_PRODUCT_OUT}/system/framework/framework-res.apk
+
+rm resources.arsc
+aapt2 compile --dir res -o compiled.flata
+aapt2 link -I $FRAMEWORK_RES_APK --manifest AndroidManifest.xml -o loader.apk compiled.flata
+unzip loader.apk resources.arsc
+rm loader.apk
+rm compiled.flata
diff --git a/libs/androidfw/tests/data/loader/res/values/public.xml b/libs/androidfw/tests/data/loader/res/values/public.xml
new file mode 100644
index 0000000..3293229
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/res/values/public.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <public type="string" name="overlayable11" id="0x7f01000b" />
+</resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/loader/res/values/values.xml b/libs/androidfw/tests/data/loader/res/values/values.xml
new file mode 100644
index 0000000..0653536
--- /dev/null
+++ b/libs/androidfw/tests/data/loader/res/values/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="overlayable11">loader</string>
+</resources>
diff --git a/libs/androidfw/tests/data/loader/resources.arsc b/libs/androidfw/tests/data/loader/resources.arsc
index 2c881f2..2bdb288 100644
--- a/libs/androidfw/tests/data/loader/resources.arsc
+++ b/libs/androidfw/tests/data/loader/resources.arsc
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/AndroidManifest.xml b/libs/androidfw/tests/data/overlay/AndroidManifest.xml
index a56ac18..28a1148 100644
--- a/libs/androidfw/tests/data/overlay/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/overlay/AndroidManifest.xml
@@ -15,7 +15,9 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.test.basic">
-    <application>
-    </application>
+    package="com.android.test.overlay">
+    <overlay
+        android:targetPackage="com.android.test.basic"
+        android:targetName="OverlayableResources3"
+        android:resourcesMap="@xml/overlays"/>
 </manifest>
diff --git a/libs/androidfw/tests/data/overlay/R.h b/libs/androidfw/tests/data/overlay/R.h
new file mode 100644
index 0000000..f3dbed2
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/R.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef TESTS_DATA_OVERLAY_R_H_
+#define TESTS_DATA_OVERLAY_R_H_
+
+#include <cstdint>
+
+namespace com {
+namespace android {
+namespace overlay {
+
+struct R {
+  struct string {
+    enum : uint32_t {
+      internal = 0x7f040000,
+    };
+  };
+};
+
+}  // namespace overlay
+}  // namespace android
+}  // namespace com
+
+#endif /* TESTS_DATA_OVERLAY_R_H_ */
diff --git a/libs/androidfw/tests/data/overlay/build b/libs/androidfw/tests/data/overlay/build
index 716b1bd..99dfd63 100755
--- a/libs/androidfw/tests/data/overlay/build
+++ b/libs/androidfw/tests/data/overlay/build
@@ -17,6 +17,15 @@
 
 set -e
 
+FRAMEWORK_RES_APK=${ANDROID_PRODUCT_OUT}/system/framework/framework-res.apk
+
 aapt2 compile --dir res -o compiled.flata
-aapt2 link --manifest AndroidManifest.xml -o overlay.apk compiled.flata
+aapt2 link -I $FRAMEWORK_RES_APK --manifest AndroidManifest.xml -o overlay.apk compiled.flata \
+    --no-auto-version
 rm compiled.flata
+
+# Navigate back a directory so the idmap can find the overlays in the test data directory when being
+# loaded during testing.
+cd ../
+idmap2 create --target-apk-path overlayable/overlayable.apk \
+    --overlay-apk-path overlay/overlay.apk --idmap-path overlay/overlay.idmap
diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk
index d37874d..c594b8e 100644
--- a/libs/androidfw/tests/data/overlay/overlay.apk
+++ b/libs/androidfw/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap
new file mode 100644
index 0000000..27cf792f
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/overlay.idmap
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/res/layout/hello_view.xml b/libs/androidfw/tests/data/overlay/res/layout/hello_view.xml
new file mode 100644
index 0000000..54dc6c0
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/res/layout/hello_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/hello_view"
+    android:text="@android:string/yes"
+    app:max_lines="4"/>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlay/res/values/values.xml b/libs/androidfw/tests/data/overlay/res/values/values.xml
index 8e4417e..ba018ec 100644
--- a/libs/androidfw/tests/data/overlay/res/values/values.xml
+++ b/libs/androidfw/tests/data/overlay/res/values/values.xml
@@ -13,13 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <resources>
-    <string name="test2">test2-overlay</string>
-    <integer-array name="integerArray1">
-        <item>10</item>
-        <item>11</item>
-    </integer-array>
-    <public type="animator" name="unoverlaid" id="0x7fff0000" />
-    <item type="animator" name="unoverlaid">@null</item>
+    <string name="overlay1">Overlay One</string>
+    <string name="overlay2">Overlay Two</string>
+    <string name="overlay3">@string/internal</string>
+    <string name="overlay4">@string/overlay2</string>
+    <string name="internal">Internal</string>
+    <attr name="max_lines" format="integer" />
 </resources>
diff --git a/libs/androidfw/tests/data/overlay/res/xml/overlays.xml b/libs/androidfw/tests/data/overlay/res/xml/overlays.xml
new file mode 100644
index 0000000..9eca2fa
--- /dev/null
+++ b/libs/androidfw/tests/data/overlay/res/xml/overlays.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language language governing permissions and
+     limitations under the License.
+-->
+<overlay>
+    <!-- Overlays string/overlayable5 with the string "Overlay One". -->
+    <item target="string/overlayable5" value="@string/overlay1"/>
+
+    <!-- Overlays string/overlayable6 and string/overlayable7 with the string "Overlay Two". -->
+    <item target="string/overlayable7" value="@string/overlay2" />
+    <item target="string/overlayable6" value="@string/overlay2" />
+
+    <!-- Overlays string/overlayable8 with a reference to @string/internal. -->
+    <item target="string/overlayable8" value="@string/overlay3" />
+
+    <!-- Overlays string/overlayable9 with a reference to @string/overlay2. The reference to
+         @string/overlay2 should be rewritten to @string/overlayable7 in the target. -->
+    <item target="string/overlayable9" value="@string/overlay4" />
+
+    <!-- Overlays string/overlayable10 with the string "yes". -->
+    <item target="string/overlayable10" value="@android:string/yes" />
+
+    <!-- Overlays string/overlayable11 with the string "Hardcoded string". -->
+    <item target="string/overlayable11" value="Hardcoded string" />
+
+    <!-- Overlays string/overlayable10 with the string "yes". -->
+    <item target="integer/config_int" value="42" />
+
+    <!-- @attr/max_lines and @id/hello_view should be rewritten to @attr/max_lines and
+         @id/hello_view in the target. -->
+    <item target="layout/hello_view" value="@layout/hello_view" />
+    <item target="attr/max_lines" value="@attr/max_lines" />
+    <item target="id/hello_view" value="@id/hello_view" />
+</overlay>
+
+
diff --git a/libs/androidfw/tests/data/overlayable/R.h b/libs/androidfw/tests/data/overlayable/R.h
index e46e264d..35125a6 100644
--- a/libs/androidfw/tests/data/overlayable/R.h
+++ b/libs/androidfw/tests/data/overlayable/R.h
@@ -31,6 +31,43 @@
       overlayable2 = 0x7f010002,
       overlayable3 = 0x7f010003,
       overlayable4 = 0x7f010004,
+      overlayable5 = 0x7f010005,
+      overlayable6 = 0x7f010006,
+      overlayable7 = 0x7f010007,
+      overlayable8 = 0x7f010008,
+      overlayable9 = 0x7f010009,
+      overlayable10 = 0x7f01000a,
+      overlayable11 = 0x7f01000b,
+    };
+  };
+
+  struct attr {
+    enum : uint32_t  {
+      max_lines = 0x7f020000,
+    };
+  };
+
+  struct boolean {
+    enum : uint32_t {
+      config_bool = 0x7f030000,
+    };
+  };
+
+  struct id {
+    enum : uint32_t  {
+      hello_view = 0x7f040000,
+    };
+  };
+
+  struct integer {
+    enum : uint32_t {
+      config_integer = 0x7f050000,
+    };
+  };
+
+  struct layout {
+    enum : uint32_t  {
+      hello_view = 0x7f060000,
     };
   };
 };
diff --git a/libs/androidfw/tests/data/overlayable/build b/libs/androidfw/tests/data/overlayable/build
index 98fdc51..0aa97d6 100755
--- a/libs/androidfw/tests/data/overlayable/build
+++ b/libs/androidfw/tests/data/overlayable/build
@@ -17,6 +17,9 @@
 
 set -e
 
+FRAMEWORK_RES_APK=${ANDROID_PRODUCT_OUT}/system/framework/framework-res.apk
+
 aapt2 compile --dir res -o compiled.flata
-aapt2 link --manifest AndroidManifest.xml -o overlayable.apk compiled.flata
+aapt2 link -I $FRAMEWORK_RES_APK --manifest AndroidManifest.xml -o overlayable.apk compiled.flata \
+    --no-auto-version
 rm compiled.flata
diff --git a/libs/androidfw/tests/data/overlayable/overlayable.apk b/libs/androidfw/tests/data/overlayable/overlayable.apk
index 047e6af..9dc9c15 100644
--- a/libs/androidfw/tests/data/overlayable/overlayable.apk
+++ b/libs/androidfw/tests/data/overlayable/overlayable.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlayable/res/layout/hello_view.xml b/libs/androidfw/tests/data/overlayable/res/layout/hello_view.xml
new file mode 100644
index 0000000..268118a
--- /dev/null
+++ b/libs/androidfw/tests/data/overlayable/res/layout/hello_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/hello_view"
+    android:text="None"
+    app:max_lines="0"/>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
index fcdbe94..b3e8f7d 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
@@ -15,27 +15,41 @@
 -->
 
 <resources>
-<overlayable name="OverlayableResources1" actor="overlay://theme">
-    <!-- Any overlay can overlay the value of @string/overlayable1 -->
-    <item type="string" name="overlayable1" />
+    <overlayable name="OverlayableResources1" actor="overlay://theme">
+        <!-- Any overlay on the product or system partition can overlay the value of
+            @string/overlayable2 -->
+        <policy type="product|system">
+            <item type="string" name="overlayable2" />
+        </policy>
 
-    <!-- Any overlay on the product or system partition can overlay the value of
-        @string/overlayable2 -->
-    <policy type="product|system">
-        <item type="string" name="overlayable2" />
-    </policy>
+        <!-- Any overlay can overlay the value of @string/overlayable4 -->
+        <policy type="public">
+            <item type="string" name="overlayable1" />
+            <item type="string" name="overlayable4" />
+        </policy>
+    </overlayable>
 
-    <!-- Any overlay can overlay the value of @string/overlayable4 -->
-    <policy type="public">
-        <item type="string" name="overlayable4" />
-    </policy>
-</overlayable>
+    <overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable">
+        <!-- Any overlay on the vendor or product partition can overlay the value of
+            @string/overlayable3 -->
+        <policy type="vendor|product">
+            <item type="string" name="overlayable3" />
+        </policy>
+    </overlayable>
 
-<overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable">
-    <!-- Any overlay on the vendor or product partition can overlay the value of
-        @string/overlayable3 -->
-    <policy type="vendor|product">
-        <item type="string" name="overlayable3" />
-    </policy>
-</overlayable>
+    <overlayable name="OverlayableResources3">
+        <policy type="public">
+            <item type="string" name="overlayable5" />
+            <item type="string" name="overlayable6" />
+            <item type="string" name="overlayable7" />
+            <item type="string" name="overlayable8" />
+            <item type="string" name="overlayable9" />
+            <item type="string" name="overlayable10" />
+            <item type="string" name="overlayable11" />
+            <item type="integer" name="config_int" />
+            <item type="id" name="hello_view" />
+            <item type="attr" name="max_lines" />
+            <item type="layout" name="hello_view" />
+        </policy>
+    </overlayable>
 </resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlayable/res/values/public.xml b/libs/androidfw/tests/data/overlayable/res/values/public.xml
index 5676d7c..042a311 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/public.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/public.xml
@@ -20,4 +20,21 @@
     <public type="string" name="overlayable2" id="0x7f010002" />
     <public type="string" name="overlayable3" id="0x7f010003" />
     <public type="string" name="overlayable4" id="0x7f010004" />
+    <public type="string" name="overlayable5" id="0x7f010005" />
+    <public type="string" name="overlayable6" id="0x7f010006" />
+    <public type="string" name="overlayable7" id="0x7f010007" />
+    <public type="string" name="overlayable8" id="0x7f010008" />
+    <public type="string" name="overlayable9" id="0x7f010009" />
+    <public type="string" name="overlayable10" id="0x7f01000a" />
+    <public type="string" name="overlayable11" id="0x7f01000b" />
+
+    <public type="attr" name="max_lines" id="0x7f020000" />
+
+    <public type="bool" name="config_bool" id="0x7f030000" />
+
+    <public type="id" name="hello_view" id="0x7f040000" />
+
+    <public type="integer" name="config_int" id="0x7f050000" />
+
+    <public type="layout" name="hello_view" id="0x7f060000" />
 </resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/overlayable/res/values/values.xml b/libs/androidfw/tests/data/overlayable/res/values/values.xml
index a86b312..235772d 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/values.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/values.xml
@@ -20,4 +20,15 @@
     <string name="overlayable2">Overlayable Two</string>
     <string name="overlayable3">Overlayable Three</string>
     <string name="overlayable4">Overlayable Four</string>
+    <string name="overlayable5">Overlayable Five</string>
+    <string name="overlayable6">Overlayable Six</string>
+    <string name="overlayable7">Overlayable Seven</string>
+    <string name="overlayable8">Overlayable Eight</string>
+    <string name="overlayable9">Overlayable Nine</string>
+    <string name="overlayable10">Overlayable Ten</string>
+    <string name="overlayable11">Overlayable Eleven</string>
+
+    <integer name="config_int">0</integer>
+    <bool name="config_bool">false</bool>
+    <attr name="max_lines" format="integer" />
 </resources>
diff --git a/libs/androidfw/tests/data/system/R.h b/libs/androidfw/tests/data/system/R.h
index 3741074..c0160c0 100644
--- a/libs/androidfw/tests/data/system/R.h
+++ b/libs/androidfw/tests/data/system/R.h
@@ -43,7 +43,8 @@
 
   struct string {
     enum : uint32_t {
-      cancel = 0x01040000,
+      no = 0x01040009,
+      yes = 0x01040013,
     };
   };
 };
diff --git a/libs/androidfw/tests/data/system/res/values/public.xml b/libs/androidfw/tests/data/system/res/values/public.xml
new file mode 100644
index 0000000..077874d
--- /dev/null
+++ b/libs/androidfw/tests/data/system/res/values/public.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <public type="string" name="no" id="0x01040009" />
+    <public type="string" name="yes" id="0x01040013" />
+</resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/system/res/values/values.xml b/libs/androidfw/tests/data/system/res/values/values.xml
new file mode 100644
index 0000000..0629c1d1
--- /dev/null
+++ b/libs/androidfw/tests/data/system/res/values/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     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.
+-->
+
+<resources>
+    <string name="yes">yes</string>
+    <string name="no">no</string>
+</resources>
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/system/system.apk b/libs/androidfw/tests/data/system/system.apk
index 9045d6c..1f7e007 100644
--- a/libs/androidfw/tests/data/system/system.apk
+++ b/libs/androidfw/tests/data/system/system.apk
Binary files differ
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 8a76d6b..6e3e43a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -242,7 +242,8 @@
         nsecs_t queueDuration;
     };
 
-    RingBuffer<SwapHistory, 3> mSwapHistory;
+    // Need at least 4 because we do quad buffer. Add a 5th for good measure.
+    RingBuffer<SwapHistory, 5> mSwapHistory;
     int64_t mFrameNumber = -1;
 
     // last vsync for a dropped frame due to stuffed queue
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index daa2e08..79bec92 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -31,6 +31,7 @@
 import android.location.LocationRequest;
 import android.location.LocationTime;
 import android.os.Bundle;
+import android.os.ICancellationSignal;
 
 import com.android.internal.location.ProviderProperties;
 
@@ -41,17 +42,23 @@
  */
 interface ILocationManager
 {
+    Location getLastLocation(in LocationRequest request, String packageName, String featureId);
+    boolean getCurrentLocation(in LocationRequest request,
+            in ICancellationSignal cancellationSignal, in ILocationListener listener,
+            String packageName, String featureId, String listenerIdentifier);
+
     void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
-            in PendingIntent intent, String packageName, String listenerIdentifier);
+            in PendingIntent intent, String packageName, String featureId,
+            String listenerIdentifier);
     void removeUpdates(in ILocationListener listener, in PendingIntent intent, String packageName);
 
     void requestGeofence(in LocationRequest request, in Geofence geofence,
-            in PendingIntent intent, String packageName, String listenerIdentifier);
+            in PendingIntent intent, String packageName, String featureId,
+            String listenerIdentifier);
     void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName);
 
-    Location getLastLocation(in LocationRequest request, String packageName);
-
-    boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName);
+    boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName,
+            String featureId);
     void unregisterGnssStatusCallback(IGnssStatusListener callback);
 
     boolean geocoderIsPresent();
@@ -65,14 +72,14 @@
     boolean sendNiResponse(int notifId, int userResponse);
 
     boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener,
-             String packageName, String listenerIdentifier);
+             String packageName, String featureId, String listenerIdentifier);
     void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
             in String packageName);
     long getGnssCapabilities(in String packageName);
     void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
 
     boolean addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener,
-             String packageName, String listenerIdentifier);
+             String packageName, String featureId, String listenerIdentifier);
     void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener);
 
     int getGnssYearOfHardware();
@@ -80,7 +87,7 @@
 
     int getGnssBatchSize(String packageName);
     boolean addGnssBatchingCallback(in IBatchedLocationCallback callback, String packageName,
-             String listenerIdentifier);
+             String featureId, String listenerIdentifier);
     void removeGnssBatchingCallback();
     boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName);
     void flushGnssBatch(String packageName);
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 6824be8..27274d1 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -1211,7 +1211,8 @@
     }
 
     /**
-     * Attaches an extra {@link Location} to this Location.
+     * Attaches an extra {@link Location} to this Location. This is useful for location providers
+     * to set the {@link #EXTRA_NO_GPS_LOCATION} extra to provide coarse locations for clients.
      *
      * @param key the key associated with the Location extra
      * @param value the Location to attach
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 0b3e1c3..d3db9d8 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 import static android.Manifest.permission.LOCATION_HARDWARE;
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+import static android.app.AlarmManager.ELAPSED_REALTIME;
 
 import android.Manifest;
 import android.annotation.CallbackExecutor;
@@ -31,17 +32,21 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.HandlerExecutor;
+import android.os.ICancellationSignal;
 import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArrayMap;
@@ -55,6 +60,7 @@
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
+import java.util.function.Consumer;
 
 /**
  * This class provides access to the system location services. These services allow applications to
@@ -77,22 +83,20 @@
 
     /**
      * Name of the network location provider.
-     * <p>This provider determines location based on
-     * availability of cell tower and WiFi access points. Results are retrieved
-     * by means of a network lookup.
+     *
+     * <p>This provider determines location based on nearby of cell tower and WiFi access points.
+     * Results are retrieved by means of a network lookup.
      */
     public static final String NETWORK_PROVIDER = "network";
 
     /**
-     * Name of the GPS location provider.
+     * Name of the GNSS location provider.
      *
-     * <p>This provider determines location using
-     * satellites. Depending on conditions, this provider may take a while to return
-     * a location fix. Requires the permission
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+     * <p>This provider determines location using GNSS satellites. Depending on conditions, this
+     * provider may take a while to return a location fix. Requires the
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission.
      *
-     * <p> The extras Bundle for the GPS location provider can contain the
-     * following key/value pairs:
+     * <p>The extras Bundle for the GPS location provider can contain the following key/value pairs:
      * <ul>
      * <li> satellites - the number of satellites used to derive the fix
      * </ul>
@@ -100,26 +104,24 @@
     public static final String GPS_PROVIDER = "gps";
 
     /**
-     * A special location provider for receiving locations without actually initiating
-     * a location fix.
+     * A special location provider for receiving locations without actually initiating a location
+     * fix.
      *
-     * <p>This provider can be used to passively receive location updates
-     * when other applications or services request them without actually requesting
-     * the locations yourself.  This provider will return locations generated by other
-     * providers.  You can query the {@link Location#getProvider()} method to determine
-     * the origin of the location update. Requires the permission
-     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}, although if the GPS is
-     * not enabled this provider might only return coarse fixes.
+     * <p>This provider can be used to passively receive location updates when other applications or
+     * services request them without actually requesting the locations yourself. This provider will
+     * only return locations generated by other providers.  You can query the
+     * {@link Location#getProvider()} method to determine the actual provider that supplied the
+     * location update. Requires the {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
+     * permission, although there is no guarantee of fine locations.
      */
     public static final String PASSIVE_PROVIDER = "passive";
 
     /**
-     * Name of the Fused location provider.
+     * The fused location provider.
      *
-     * <p>This provider combines inputs for all possible location sources
-     * to provide the best possible Location fix. It is implicitly
-     * used for all API's that involve the {@link LocationRequest}
-     * object.
+     * <p>This provider combines may combine inputs from several location sources to provide the
+     * best possible location fix. It is implicitly used for all API's that involve the
+     * {@link LocationRequest} object.
      *
      * @hide
      */
@@ -228,6 +230,8 @@
     public static final String METADATA_SETTINGS_FOOTER_STRING =
             "com.android.settings.location.FOOTER_STRING";
 
+    private static final long GET_CURRENT_LOCATION_TIMEOUT_MS = 30 * 1000;
+
     private final Context mContext;
 
     @UnsupportedAppUsage
@@ -511,7 +515,8 @@
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public Location getLastLocation() {
         try {
-            return mService.getLastLocation(null, mContext.getPackageName());
+            return mService.getLastLocation(null, mContext.getPackageName(),
+                    mContext.getFeatureId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -522,6 +527,13 @@
      * location. The returned location may be quite old in some circumstances, so the age of the
      * location should always be checked.
      *
+     * <p>This will never activate sensors to compute a new location, and will only ever return a
+     * cached location.
+     *
+     * <p>See also {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} which
+     * will always attempt to return a current location, but will potentially use additional power
+     * in the course of the attempt as compared to this method.
+     *
      * @param provider the name of the provider
      * @return the last known location for the given provider, or null if not available
      * @throws SecurityException if no suitable permission is present
@@ -536,7 +548,8 @@
                 provider, 0, 0, true);
 
         try {
-            return mService.getLastLocation(request, mContext.getPackageName());
+            return mService.getLastLocation(request, mContext.getPackageName(),
+                    mContext.getFeatureId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -550,36 +563,117 @@
      * @return A identifying string
      */
     private static String getListenerIdentifier(@NonNull Object listener) {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append(listener.getClass().getName());
-        sb.append('@');
-        sb.append(Integer.toHexString(System.identityHashCode(listener)));
-
-        return sb.toString();
+        return listener.getClass().getName()
+                + '@'
+                + Integer.toHexString(System.identityHashCode(listener));
     }
 
     /**
-     * Register for a single location update using the named provider and
-     * a callback.
+     * Asynchronously returns a single current location fix. This may activate sensors in order to
+     * compute a new location, unlike {@link #getLastKnownLocation(String)}, which will only return
+     * a cached fix if available. The given callback will be invoked once and only once, either with
+     * a valid location fix or with a null location fix if the provider was unable to generate a
+     * valid location.
      *
-     * <p>See {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)}
-     * for more detail on how to use this method.
+     * <p>A client may supply an optional {@link CancellationSignal}. If this is used to cancel the
+     * operation, no callback should be expected after the cancellation.
+     *
+     * <p>This method may return locations from the very recent past (on the order of several
+     * seconds), but will never return older locations (for example, several minutes old or older).
+     * Clients may rely upon the guarantee that if this method returns a location, it will represent
+     * the best estimation of the location of the device in the present moment.
+     *
+     * <p>Clients calling this method from the background may notice that the method fails to
+     * determine a valid location fix more often than while in the foreground. Background
+     * applications may be throttled in their location accesses to some degree.
+     *
+     * @param provider           the name of the provider with which to register
+     * @param cancellationSignal an optional signal that allows for cancelling this call
+     * @param executor           the callback will take place on this {@link Executor}
+     * @param consumer           the callback invoked with either a {@link Location} or null
+     *
+     * @throws IllegalArgumentException if provider is null or doesn't exist
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if consumer is null
+     * @throws SecurityException        if no suitable permission is present
+     */
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
+    public void getCurrentLocation(@NonNull String provider,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
+        getCurrentLocation(LocationRequest.createFromDeprecatedProvider(provider, 0, 0, true),
+                cancellationSignal, executor, consumer);
+    }
+
+    /**
+     * Asynchronously returns a single current location fix based on the given
+     * {@link LocationRequest}.
+     *
+     * <p>See {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)} for more
+     * information.
+     *
+     * @param locationRequest    the location request containing location parameters
+     * @param cancellationSignal an optional signal that allows for cancelling this call
+     * @param executor           the callback will take place on this {@link Executor}
+     * @param consumer           the callback invoked with either a {@link Location} or null
+     *
+     * @throws IllegalArgumentException if provider is null or doesn't exist
+     * @throws IllegalArgumentException if executor is null
+     * @throws IllegalArgumentException if consumer is null
+     * @throws SecurityException        if no suitable permission is present
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
+    public void getCurrentLocation(@NonNull LocationRequest locationRequest,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
+        LocationRequest currentLocationRequest = new LocationRequest(locationRequest)
+                .setNumUpdates(1).setExpireIn(GET_CURRENT_LOCATION_TIMEOUT_MS);
+
+        GetCurrentLocationTransport listenerTransport = new GetCurrentLocationTransport(executor,
+                consumer);
+
+        if (cancellationSignal != null) {
+            cancellationSignal.throwIfCanceled();
+        }
+
+        ICancellationSignal remoteCancellationSignal = CancellationSignal.createTransport();
+
+        try {
+            if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal,
+                    listenerTransport, mContext.getPackageName(), mContext.getFeatureId(),
+                    getListenerIdentifier(consumer))) {
+                listenerTransport.register(mContext.getSystemService(AlarmManager.class),
+                        remoteCancellationSignal);
+                if (cancellationSignal != null) {
+                    cancellationSignal.setOnCancelListener(listenerTransport::cancel);
+                }
+            } else {
+                listenerTransport.fail();
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Register for a single location update using the named provider and a callback.
+     *
+     * <p>See {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)} for
+     * more detail on how to use this method.
      *
      * @param provider the name of the provider with which to register
-     * @param listener a {@link LocationListener} whose
-     * {@link LocationListener#onLocationChanged} method will be called when
-     * the location update is available
-     * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the calling
-     * thread
+     * @param listener the listener to receive location updates
+     * @param looper   the looper handling listener callbacks, or null to use the looper of the
+     *                 calling thread
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @Deprecated
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
@@ -594,27 +688,21 @@
     }
 
     /**
-     * Register for a single location update using a Criteria and
-     * a callback.
+     * Register for a single location update using a Criteria and a callback.
      *
-     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
-     * for more detail on how to use this method.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
+     * on how to use this method.
      *
-     * @param criteria contains parameters for the location manager to choose the
-     * appropriate provider and parameters to compute the location
-     * @param listener a {@link LocationListener} whose
-     * {@link LocationListener#onLocationChanged} method will be called when
-     * the location update is available
-     * @param looper a Looper object whose message queue will be used to
-     * implement the callback mechanism, or null to make callbacks on the calling
-     * thread
+     * @param criteria contains parameters to choose the appropriate provider for location updates
+     * @param listener the listener to receive location updates
+     * @param looper   the looper handling listener callbacks, or null to use the looper of the
+     *                 calling thread
      *
      * @throws IllegalArgumentException if criteria is null
      * @throws IllegalArgumentException if listener is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestSingleUpdate(
@@ -632,54 +720,54 @@
     /**
      * Register for a single location update using a named provider and pending intent.
      *
-     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
-     * for more detail on how to use this method.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
+     * on how to use this method.
      *
-     * @param provider the name of the provider with which to register
-     * @param intent a {@link PendingIntent} to be sent for the location update
+     * @param provider      the name of the provider with which to register
+     * @param pendingIntent the pending intent to send location updates
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(@NonNull String provider, @NonNull PendingIntent intent) {
+    public void requestSingleUpdate(@NonNull String provider,
+            @NonNull PendingIntent pendingIntent) {
         Preconditions.checkArgument(provider != null, "invalid null provider");
-        checkPendingIntent(intent);
+        checkPendingIntent(pendingIntent);
 
         LocationRequest request = LocationRequest.createFromDeprecatedProvider(
                 provider, 0, 0, true);
-        requestLocationUpdates(request, intent);
+        requestLocationUpdates(request, pendingIntent);
     }
 
     /**
      * Register for a single location update using a Criteria and pending intent.
      *
-     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)}
-     * for more detail on how to use this method.
+     * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail
+     * on how to use this method.
      *
-     * @param criteria contains parameters for the location manager to choose the
-     * appropriate provider and parameters to compute the location
-     * @param intent a {@link PendingIntent} to be sent for the location update
+     * @param criteria      contains parameters to choose the appropriate provider for location
+     *                      updates
+     * @param pendingIntent the pending intent to send location updates
      *
      * @throws IllegalArgumentException if provider is null or doesn't exist
      * @throws IllegalArgumentException if intent is null
-     * @throws SecurityException if no suitable permission is present
-     * @deprecated This method can drain much more battery than expected if it is not possible to
-     * calculate location. Prefer any of the requestLocationUpdates() methods which require explicit
-     * removal.
+     * @throws SecurityException        if no suitable permission is present
+     * @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
+     * instead as it does not carry a risk of extreme battery drain.
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(@NonNull Criteria criteria, @NonNull PendingIntent intent) {
+    public void requestSingleUpdate(@NonNull Criteria criteria,
+            @NonNull PendingIntent pendingIntent) {
         Preconditions.checkArgument(criteria != null, "invalid null criteria");
-        checkPendingIntent(intent);
+        checkPendingIntent(pendingIntent);
 
         LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
                 criteria, 0, 0, true);
-        requestLocationUpdates(request, intent);
+        requestLocationUpdates(request, pendingIntent);
     }
 
     /**
@@ -999,7 +1087,8 @@
             boolean registered = false;
             try {
                 mService.requestLocationUpdates(locationRequest, transport, null,
-                        mContext.getPackageName(), getListenerIdentifier(listener));
+                        mContext.getPackageName(), mContext.getFeatureId(),
+                        getListenerIdentifier(listener));
                 registered = true;
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -1044,7 +1133,8 @@
 
         try {
             mService.requestLocationUpdates(locationRequest, null, pendingIntent,
-                    mContext.getPackageName(), getListenerIdentifier(pendingIntent));
+                    mContext.getPackageName(), mContext.getFeatureId(),
+                    getListenerIdentifier(pendingIntent));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1508,7 +1598,7 @@
         LocationRequest request = new LocationRequest().setExpireIn(expiration);
         try {
             mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
-                    getListenerIdentifier(intent));
+                    mContext.getFeatureId(), getListenerIdentifier(intent));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1586,7 +1676,7 @@
 
         try {
             mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
-                    getListenerIdentifier(intent));
+                    mContext.getFeatureId(), getListenerIdentifier(intent));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1971,7 +2061,7 @@
     public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {}
 
     /**
-     * Registers a GPS Measurement callback.
+     * Registers a GPS Measurement callback which will run on a binder thread.
      *
      * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
@@ -1983,7 +2073,7 @@
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssMeasurementsCallback(
             @NonNull GnssMeasurementsEvent.Callback callback) {
-        return registerGnssMeasurementsCallback(callback, null);
+        return registerGnssMeasurementsCallback(Runnable::run, callback);
     }
 
     /**
@@ -2093,7 +2183,7 @@
     public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {}
 
     /**
-     * Registers a GNSS Navigation Message callback.
+     * Registers a GNSS Navigation Message callback which will run on a binder thread.
      *
      * @param callback a {@link GnssNavigationMessage.Callback} object to register.
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
@@ -2104,7 +2194,7 @@
     @Deprecated
     public boolean registerGnssNavigationMessageCallback(
             @NonNull GnssNavigationMessage.Callback callback) {
-        return registerGnssNavigationMessageCallback(callback, null);
+        return registerGnssNavigationMessageCallback(Runnable::run, callback);
     }
 
     /**
@@ -2295,6 +2385,127 @@
         }
     }
 
+    private static class GetCurrentLocationTransport extends ILocationListener.Stub implements
+            AlarmManager.OnAlarmListener {
+
+        @GuardedBy("this")
+        @Nullable
+        private Executor mExecutor;
+
+        @GuardedBy("this")
+        @Nullable
+        private Consumer<Location> mConsumer;
+
+        @GuardedBy("this")
+        @Nullable
+        private AlarmManager mAlarmManager;
+
+        @GuardedBy("this")
+        @Nullable
+        private ICancellationSignal mRemoteCancellationSignal;
+
+        private GetCurrentLocationTransport(Executor executor, Consumer<Location> consumer) {
+            Preconditions.checkArgument(executor != null, "illegal null executor");
+            Preconditions.checkArgument(consumer != null, "illegal null consumer");
+            mExecutor = executor;
+            mConsumer = consumer;
+            mAlarmManager = null;
+            mRemoteCancellationSignal = null;
+        }
+
+        public synchronized void register(AlarmManager alarmManager,
+                ICancellationSignal remoteCancellationSignal) {
+            if (mConsumer == null) {
+                return;
+            }
+
+            mAlarmManager = alarmManager;
+            mAlarmManager.set(
+                    ELAPSED_REALTIME,
+                    SystemClock.elapsedRealtime() + GET_CURRENT_LOCATION_TIMEOUT_MS,
+                    "GetCurrentLocation",
+                    this,
+                    null);
+
+            mRemoteCancellationSignal = remoteCancellationSignal;
+        }
+
+        public synchronized void cancel() {
+            mExecutor = null;
+            mConsumer = null;
+
+            if (mAlarmManager != null) {
+                mAlarmManager.cancel(this);
+                mAlarmManager = null;
+            }
+
+            if (mRemoteCancellationSignal != null) {
+                try {
+                    mRemoteCancellationSignal.cancel();
+                } catch (RemoteException e) {
+                    // ignore
+                }
+                mRemoteCancellationSignal = null;
+            }
+        }
+
+        public void fail() {
+            deliverResult(null);
+        }
+
+        @Override
+        public void onAlarm() {
+            synchronized (this) {
+                // save ourselves a pointless x-process call to cancel the alarm
+                mAlarmManager = null;
+            }
+
+            deliverResult(null);
+        }
+
+        @Override
+        public void onLocationChanged(Location location) {
+            synchronized (this) {
+                // save ourselves a pointless x-process call to cancel the location request
+                mRemoteCancellationSignal = null;
+            }
+
+            deliverResult(location);
+        }
+
+        @Override
+        public void onStatusChanged(String provider, int status, Bundle extras) {}
+
+        @Override
+        public void onProviderEnabled(String provider) {}
+
+        @Override
+        public void onProviderDisabled(String provider) {
+            // in the event of the provider being disabled it is unlikely that we will get further
+            // locations, so fail early so the client isn't left waiting hopelessly
+            deliverResult(null);
+        }
+
+        private synchronized void deliverResult(@Nullable Location location) {
+            if (mExecutor == null) {
+                return;
+            }
+
+            mExecutor.execute(() -> {
+                Consumer<Location> consumer;
+                synchronized (GetCurrentLocationTransport.this) {
+                    if (mConsumer == null) {
+                        return;
+                    }
+                    consumer = mConsumer;
+                    cancel();
+                }
+
+                consumer.accept(location);
+            });
+        }
+    }
+
     private class LocationListenerTransport extends ILocationListener.Stub {
 
         private final LocationListener mListener;
@@ -2541,7 +2752,7 @@
 
             mListenerTransport = new GnssStatusListener();
             return mService.registerGnssStatusCallback(mListenerTransport,
-                    mContext.getPackageName());
+                    mContext.getPackageName(), mContext.getFeatureId());
         }
 
         @Override
@@ -2601,7 +2812,8 @@
 
             mListenerTransport = new GnssMeasurementsListener();
             return mService.addGnssMeasurementsListener(mListenerTransport,
-                    mContext.getPackageName(), "gnss measurement callback");
+                    mContext.getPackageName(), mContext.getFeatureId(),
+                    "gnss measurement callback");
         }
 
         @Override
@@ -2637,7 +2849,8 @@
 
             mListenerTransport = new GnssNavigationMessageListener();
             return mService.addGnssNavigationMessageListener(mListenerTransport,
-                    mContext.getPackageName(), "gnss navigation callback");
+                    mContext.getPackageName(), mContext.getFeatureId(),
+                    "gnss navigation callback");
         }
 
         @Override
@@ -2673,7 +2886,7 @@
 
             mListenerTransport = new BatchedLocationCallback();
             return mService.addGnssBatchingCallback(mListenerTransport, mContext.getPackageName(),
-                     "batched location callback");
+                     mContext.getFeatureId(), "batched location callback");
         }
 
         @Override
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 0902acf..0f38f7f 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -30,6 +30,8 @@
 import android.os.WorkSource;
 import android.util.TimeUtils;
 
+import com.android.internal.util.Preconditions;
+
 
 /**
  * A data object that contains quality of service parameters for requests
@@ -195,6 +197,8 @@
     @NonNull
     public static LocationRequest createFromDeprecatedProvider(
             @NonNull String provider, long minTime, float minDistance, boolean singleShot) {
+        Preconditions.checkArgument(provider != null, "invalid null provider");
+
         if (minTime < 0) minTime = 0;
         if (minDistance < 0) minDistance = 0;
 
@@ -222,6 +226,8 @@
     @NonNull
     public static LocationRequest createFromDeprecatedCriteria(
             @NonNull Criteria criteria, long minTime, float minDistance, boolean singleShot) {
+        Preconditions.checkArgument(criteria != null, "invalid null criteria");
+
         if (minTime < 0) minTime = 0;
         if (minDistance < 0) minDistance = 0;
 
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 65d3ffc..ac5a9f8 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -670,7 +670,7 @@
                     mUsage = usage;
                     break;
                 default:
-                    mUsage = USAGE_UNKNOWN;
+                    throw new IllegalArgumentException("Invalid usage " + usage);
             }
             return this;
         }
@@ -696,7 +696,7 @@
                     mContentType = contentType;
                     break;
                 default:
-                    mContentType = CONTENT_TYPE_UNKNOWN;
+                    throw new IllegalArgumentException("Invalid content type " + contentType);
             }
             return this;
         }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 53bc65d..bb731a8 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -26,6 +27,8 @@
 import android.media.audiopolicy.AudioMix;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Map;
 
@@ -431,6 +434,50 @@
     public static final int DEAD_OBJECT        = -6;
     public static final int WOULD_BLOCK        = -7;
 
+    /** @hide */
+    @IntDef({
+            SUCCESS,
+            ERROR,
+            BAD_VALUE,
+            INVALID_OPERATION,
+            PERMISSION_DENIED,
+            NO_INIT,
+            DEAD_OBJECT,
+            WOULD_BLOCK
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AudioSystemError {}
+
+    /**
+     * Convert an int error value to its String value for readability.
+     * Accepted error values are the java AudioSystem errors, matching android_media_AudioErrors.h,
+     * which map onto the native status_t type.
+     * @param error one of the java AudioSystem errors
+     * @return a human-readable string
+     */
+    public static String audioSystemErrorToString(@AudioSystemError int error) {
+        switch(error) {
+            case SUCCESS:
+                return "SUCCESS";
+            case ERROR:
+                return "ERROR";
+            case BAD_VALUE:
+                return "BAD_VALUE";
+            case INVALID_OPERATION:
+                return "INVALID_OPERATION";
+            case PERMISSION_DENIED:
+                return "PERMISSION_DENIED";
+            case NO_INIT:
+                return "NO_INIT";
+            case DEAD_OBJECT:
+                return "DEAD_OBJECT";
+            case WOULD_BLOCK:
+                return "WOULD_BLOCK";
+            default:
+                return ("unknown error:" + error);
+        }
+    }
+
     /*
      * AudioPolicyService methods
      */
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index b12e647..e85b3ff9 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -17,18 +17,17 @@
 package android.media;
 
 
-import java.io.FileDescriptor;
-import java.lang.ref.WeakReference;
-import java.lang.CloneNotSupportedException;
-
 import android.annotation.UnsupportedAppUsage;
 import android.content.res.AssetFileDescriptor;
-import android.os.Looper;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 
+import java.io.FileDescriptor;
+import java.lang.ref.WeakReference;
+
 /**
  * JetPlayer provides access to JET content playback and control.
  * 
@@ -120,6 +119,9 @@
     
     private static JetPlayer singletonRef;
     
+    static {
+        System.loadLibrary("media_jni");
+    }
     
     //--------------------------------
     // Used exclusively by native code
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 7ed431d..cc5ddeb 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -224,7 +224,7 @@
      * @return The meta data value associate with the given keyCode on success;
      * null on failure.
      */
-    public native String extractMetadata(int keyCode);
+    public native @Nullable String extractMetadata(int keyCode);
 
     /**
      * This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)}
@@ -255,7 +255,7 @@
      *
      * @see {@link #getFrameAtTime(long, int, BitmapParams)}
      */
-    public Bitmap getFrameAtTime(long timeUs, @Option int option) {
+    public @Nullable Bitmap getFrameAtTime(long timeUs, @Option int option) {
         if (option < OPTION_PREVIOUS_SYNC ||
             option > OPTION_CLOSEST) {
             throw new IllegalArgumentException("Unsupported option: " + option);
@@ -301,7 +301,7 @@
      *
      * @see {@link #getFrameAtTime(long, int)}
      */
-    public Bitmap getFrameAtTime(
+    public @Nullable Bitmap getFrameAtTime(
             long timeUs, @Option int option, @NonNull BitmapParams params) {
         if (option < OPTION_PREVIOUS_SYNC ||
             option > OPTION_CLOSEST) {
@@ -343,7 +343,7 @@
      *         is less than or equal to 0.
      * @see {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)}
      */
-    public Bitmap getScaledFrameAtTime(
+    public @Nullable Bitmap getScaledFrameAtTime(
             long timeUs, @Option int option, int dstWidth, int dstHeight) {
         validate(option, dstWidth, dstHeight);
         return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, null);
@@ -388,7 +388,7 @@
      *         is less than or equal to 0.
      * @see {@link #getScaledFrameAtTime(long, int, int, int)}
      */
-    public Bitmap getScaledFrameAtTime(long timeUs, @Option int option,
+    public @Nullable Bitmap getScaledFrameAtTime(long timeUs, @Option int option,
             int dstWidth, int dstHeight, @NonNull BitmapParams params) {
         validate(option, dstWidth, dstHeight);
         return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, params);
@@ -430,7 +430,7 @@
      *
      * @see #getFrameAtTime(long, int)
      */
-    public Bitmap getFrameAtTime(long timeUs) {
+    public @Nullable Bitmap getFrameAtTime(long timeUs) {
         return getFrameAtTime(timeUs, OPTION_CLOSEST_SYNC);
     }
 
@@ -452,7 +452,7 @@
      * @see #getFrameAtTime(long)
      * @see #getFrameAtTime(long, int)
      */
-    public Bitmap getFrameAtTime() {
+    public @Nullable Bitmap getFrameAtTime() {
         return _getFrameAtTime(
                 -1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/, null);
     }
@@ -528,7 +528,7 @@
      * @see #getFramesAtIndex(int, int, BitmapParams)
      * @see #getFramesAtIndex(int, int)
      */
-    public Bitmap getFrameAtIndex(int frameIndex, @NonNull BitmapParams params) {
+    public @Nullable Bitmap getFrameAtIndex(int frameIndex, @NonNull BitmapParams params) {
         List<Bitmap> bitmaps = getFramesAtIndex(frameIndex, 1, params);
         return bitmaps.get(0);
     }
@@ -550,7 +550,7 @@
      * @see #getFramesAtIndex(int, int, BitmapParams)
      * @see #getFramesAtIndex(int, int)
      */
-    public Bitmap getFrameAtIndex(int frameIndex) {
+    public @Nullable Bitmap getFrameAtIndex(int frameIndex) {
         List<Bitmap> bitmaps = getFramesAtIndex(frameIndex, 1);
         return bitmaps.get(0);
     }
@@ -653,7 +653,7 @@
      * @see #getPrimaryImage(BitmapParams)
      * @see #getPrimaryImage()
      */
-    public Bitmap getImageAtIndex(int imageIndex, @NonNull BitmapParams params) {
+    public @Nullable Bitmap getImageAtIndex(int imageIndex, @NonNull BitmapParams params) {
         return getImageAtIndexInternal(imageIndex, params);
     }
 
@@ -691,7 +691,7 @@
      * @see #getPrimaryImage(BitmapParams)
      * @see #getPrimaryImage()
      */
-    public Bitmap getImageAtIndex(int imageIndex) {
+    public @Nullable Bitmap getImageAtIndex(int imageIndex) {
         return getImageAtIndexInternal(imageIndex, null);
     }
 
@@ -713,7 +713,7 @@
      * @see #getImageAtIndex(int)
      * @see #getPrimaryImage()
      */
-    public Bitmap getPrimaryImage(@NonNull BitmapParams params) {
+    public @Nullable Bitmap getPrimaryImage(@NonNull BitmapParams params) {
         return getImageAtIndexInternal(-1, params);
     }
 
@@ -729,7 +729,7 @@
      * @see #getImageAtIndex(int)
      * @see #getPrimaryImage(BitmapParams)
      */
-    public Bitmap getPrimaryImage() {
+    public @Nullable Bitmap getPrimaryImage() {
         return getImageAtIndexInternal(-1, null);
     }
 
@@ -755,7 +755,7 @@
      *
      * @return null if no such graphic is found.
      */
-    public byte[] getEmbeddedPicture() {
+    public @Nullable byte[] getEmbeddedPicture() {
         return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY);
     }
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 7906fa3..7d107dd 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -89,6 +89,10 @@
  * of audio/video files and streams. An example on how to use the methods in
  * this class can be found in {@link android.widget.VideoView}.
  *
+ * <p>MediaPlayer is not thread-safe. Creation of and all access to player instances
+ * should be on the same thread. If registering <a href="#Callbacks">callbacks</a>,
+ * the thread must have a Looper.
+ *
  * <p>Topics covered here are:
  * <ol>
  * <li><a href="#StateDiagram">State Diagram</a>
@@ -305,7 +309,7 @@
  *         </li>
  *     <li>When the playback reaches the end of stream, the playback completes.
  *         <ul>
- *         <li>If the looping mode was being set to <var>true</var>with
+ *         <li>If the looping mode was being set to <var>true</var> with
  *         {@link #setLooping(boolean)}, the MediaPlayer object shall remain in
  *         the <em>Started</em> state.</li>
  *         <li>If the looping mode was set to <var>false
@@ -554,13 +558,13 @@
  * possible runtime errors during playback or streaming. Registration for
  * these events is done by properly setting the appropriate listeners (via calls
  * to
- * {@link #setOnPreparedListener(OnPreparedListener)}setOnPreparedListener,
- * {@link #setOnVideoSizeChangedListener(OnVideoSizeChangedListener)}setOnVideoSizeChangedListener,
- * {@link #setOnSeekCompleteListener(OnSeekCompleteListener)}setOnSeekCompleteListener,
- * {@link #setOnCompletionListener(OnCompletionListener)}setOnCompletionListener,
- * {@link #setOnBufferingUpdateListener(OnBufferingUpdateListener)}setOnBufferingUpdateListener,
- * {@link #setOnInfoListener(OnInfoListener)}setOnInfoListener,
- * {@link #setOnErrorListener(OnErrorListener)}setOnErrorListener, etc).
+ * {@link #setOnPreparedListener(OnPreparedListener) setOnPreparedListener},
+ * {@link #setOnVideoSizeChangedListener(OnVideoSizeChangedListener) setOnVideoSizeChangedListener},
+ * {@link #setOnSeekCompleteListener(OnSeekCompleteListener) setOnSeekCompleteListener},
+ * {@link #setOnCompletionListener(OnCompletionListener) setOnCompletionListener},
+ * {@link #setOnBufferingUpdateListener(OnBufferingUpdateListener) setOnBufferingUpdateListener},
+ * {@link #setOnInfoListener(OnInfoListener) setOnInfoListener},
+ * {@link #setOnErrorListener(OnErrorListener) setOnErrorListener}, etc).
  * In order to receive the respective callback
  * associated with these listeners, applications are required to create
  * MediaPlayer objects on a thread with its own Looper running (main UI
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index abd774d..59bd96f 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -79,6 +79,8 @@
     @Nullable
     final Bundle mExtras;
 
+    private final String mUniqueId;
+
     MediaRoute2Info(@NonNull Builder builder) {
         mId = builder.mId;
         mProviderId = builder.mProviderId;
@@ -90,6 +92,7 @@
         mVolumeMax = builder.mVolumeMax;
         mVolumeHandling = builder.mVolumeHandling;
         mExtras = builder.mExtras;
+        mUniqueId = createUniqueId();
     }
 
     MediaRoute2Info(@NonNull Parcel in) {
@@ -103,6 +106,15 @@
         mVolumeMax = in.readInt();
         mVolumeHandling = in.readInt();
         mExtras = in.readBundle();
+        mUniqueId = createUniqueId();
+    }
+
+    private String createUniqueId() {
+        String uniqueId = null;
+        if (mProviderId != null) {
+            uniqueId = mProviderId + ":" + mId;
+        }
+        return uniqueId;
     }
 
     /**
@@ -147,13 +159,33 @@
         return Objects.hash(mId, mName, mDescription, mSupportedCategories);
     }
 
+    /**
+     * Gets the id of the route.
+     * Use {@link #getUniqueId()} if you need a unique identifier.
+     *
+     * @see #getUniqueId()
+     */
     @NonNull
     public String getId() {
         return mId;
     }
 
     /**
-     * Gets the provider id of the route.
+     * Gets the unique id of the route. A route obtained from
+     * {@link com.android.server.media.MediaRouterService} always has a unique id.
+     *
+     * @return unique id of the route or null if it has no unique id.
+     */
+    @Nullable
+    public String getUniqueId() {
+        return mUniqueId;
+    }
+
+    /**
+     * Gets the provider id of the route. It is assigned automatically by
+     * {@link com.android.server.media.MediaRouterService}.
+     *
+     * @return provider id of the route or null if it's not set.
      * @hide
      */
     @Nullable
@@ -337,7 +369,7 @@
         @NonNull
         public Builder setProviderId(@NonNull String providerId) {
             if (TextUtils.isEmpty(providerId)) {
-                throw new IllegalArgumentException("id must not be null or empty");
+                throw new IllegalArgumentException("providerId must not be null or empty");
             }
             mProviderId = providerId;
             return this;
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 58deff2..5f5d200 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -30,7 +30,7 @@
  * @hide
  */
 public abstract class MediaRoute2ProviderService extends Service {
-    private static final String TAG = "MediaRouteProviderSrv";
+    private static final String TAG = "MR2ProviderService";
 
     public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
 
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index aca40d8..b52e2d6 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -44,7 +44,7 @@
  * @hide
  */
 public class MediaRouter2 {
-    private static final String TAG = "MediaRouter";
+    private static final String TAG = "MR2";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final Object sLock = new Object();
 
@@ -54,7 +54,8 @@
     private Context mContext;
     private final IMediaRouterService mMediaRouterService;
 
-    private CopyOnWriteArrayList<CallbackRecord> mCallbackRecords = new CopyOnWriteArrayList<>();
+    private final CopyOnWriteArrayList<CallbackRecord> mCallbackRecords =
+            new CopyOnWriteArrayList<>();
     @GuardedBy("sLock")
     private List<String> mControlCategories = Collections.emptyList();
     @GuardedBy("sLock")
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 4f2a295..0d7b6ff 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -46,7 +46,7 @@
  * @hide
  */
 public class MediaRouter2Manager {
-    private static final String TAG = "MediaRouter2Manager";
+    private static final String TAG = "MR2Manager";
     private static final Object sLock = new Object();
 
     @GuardedBy("sLock")
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index ff40442..9064e68 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -22,6 +22,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.app.Activity;
@@ -40,9 +41,11 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.MediaStore;
+import android.provider.MediaStore.MediaColumns;
 import android.provider.Settings;
 import android.provider.Settings.System;
 import android.util.Log;
@@ -1097,4 +1100,62 @@
             return null;
         }
     }
+
+    /**
+     * Ensure that ringtones have been set at least once on this device. This
+     * should be called after the device has finished scanned all media on
+     * {@link MediaStore#VOLUME_INTERNAL}, so that default ringtones can be
+     * configured.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS)
+    public static void ensureDefaultRingtones(@NonNull Context context) {
+        for (int type : new int[] {
+                TYPE_RINGTONE,
+                TYPE_NOTIFICATION,
+                TYPE_ALARM,
+        }) {
+            // Skip if we've already defined it at least once, so we don't
+            // overwrite the user changing to null
+            final String setting = getDefaultRingtoneSetting(type);
+            if (Settings.System.getInt(context.getContentResolver(), setting, 0) != 0) {
+                continue;
+            }
+
+            // Try finding the scanned ringtone
+            final String filename = getDefaultRingtoneFilename(type);
+            final Uri baseUri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
+            try (Cursor cursor = context.getContentResolver().query(baseUri,
+                    new String[] { MediaColumns._ID },
+                    MediaColumns.DISPLAY_NAME + "=?",
+                    new String[] { filename }, null)) {
+                if (cursor.moveToFirst()) {
+                    final Uri ringtoneUri = context.getContentResolver().canonicalizeOrElse(
+                            ContentUris.withAppendedId(baseUri, cursor.getLong(0)));
+                    RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri);
+                    Settings.System.putInt(context.getContentResolver(), setting, 1);
+                }
+            }
+        }
+    }
+
+    private static String getDefaultRingtoneSetting(int type) {
+        switch (type) {
+            case TYPE_RINGTONE: return "ringtone_set";
+            case TYPE_NOTIFICATION: return "notification_sound_set";
+            case TYPE_ALARM: return "alarm_alert_set";
+            default: throw new IllegalArgumentException();
+        }
+    }
+
+    private static String getDefaultRingtoneFilename(int type) {
+        switch (type) {
+            case TYPE_RINGTONE: return SystemProperties.get("ro.config.ringtone");
+            case TYPE_NOTIFICATION: return SystemProperties.get("ro.config.notification_sound");
+            case TYPE_ALARM: return SystemProperties.get("ro.config.alarm_alert");
+            default: throw new IllegalArgumentException();
+        }
+    }
 }
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 39474e1..01f1250 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -853,6 +853,10 @@
                 Log.v(TAG, "notifyVolumeAdjust: " + adjustment);
             }
         }
+
+        public void notifyUnregistration() {
+            setRegistration(null);
+        }
     };
 
     //==================================================
diff --git a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
index 107e7cd..1d58151 100644
--- a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
+++ b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
@@ -34,4 +34,8 @@
 
     // callback for volume events
     void notifyVolumeAdjust(int adjustment);
+
+    // callback for unregistration (e.g. if policy couldn't automatically be re-registered after
+    // an audioserver crash)
+    void notifyUnregistration();
 }
diff --git a/media/java/android/media/midi/MidiDeviceInfo.aidl b/media/java/android/media/midi/MidiDeviceInfo.aidl
index 5b2ac9b..a248204 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.aidl
+++ b/media/java/android/media/midi/MidiDeviceInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.media.midi;
 
-parcelable MidiDeviceInfo cpp_header "media/MidiDeviceInfo.h";
+parcelable MidiDeviceInfo cpp_header "MidiDeviceInfo.h";
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
new file mode 100644
index 0000000..0228dc9
--- /dev/null
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -0,0 +1,51 @@
+/*
+ * 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.media.tv.tuner;
+
+/**
+ * Tuner is used to interact with tuner devices.
+ *
+ * @hide
+ */
+public final class Tuner implements AutoCloseable  {
+    private static final String TAG = "MediaTvTuner";
+    private static final boolean DEBUG = false;
+
+    static {
+        System.loadLibrary("media_tv_tuner");
+        nativeInit();
+    }
+
+    public Tuner() {
+        nativeSetup();
+    }
+
+    private long mNativeContext; // used by native jMediaTuner
+
+    @Override
+    public void close() {}
+
+    /**
+     * Native Initialization.
+     */
+    private static native void nativeInit();
+
+    /**
+     * Native setup.
+     */
+    private native void nativeSetup();
+}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index bd9ea13..a596d89 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -4,6 +4,7 @@
     srcs: [
         "android_media_ImageWriter.cpp",
         "android_media_ImageReader.cpp",
+        "android_media_JetPlayer.cpp",
         "android_media_MediaCrypto.cpp",
         "android_media_MediaCodec.cpp",
         "android_media_MediaCodecList.cpp",
@@ -24,10 +25,12 @@
         "android_mtp_MtpDatabase.cpp",
         "android_mtp_MtpDevice.cpp",
         "android_mtp_MtpServer.cpp",
+        "JetPlayer.cpp",
     ],
 
     shared_libs: [
         "libandroid_runtime",
+        "libaudioclient",
         "libnativehelper",
         "libnativewindow",
         "libutils",
@@ -52,6 +55,7 @@
         "libandroidfw",
         "libhidlallocatorutils",
         "libhidlbase",
+        "libsonivox",
         "android.hardware.cas@1.0",
         "android.hardware.cas.native@1.0",
         "android.hidl.memory@1.0",
@@ -63,7 +67,10 @@
         "libmediadrm_headers",
     ],
 
-    static_libs: ["libgrallocusage"],
+    static_libs: [
+        "libgrallocusage",
+        "libmedia_midiiowrapper",
+    ],
 
     include_dirs: [
         "frameworks/base/core/jni",
@@ -116,6 +123,30 @@
     ],
 }
 
+cc_library_shared {
+    name: "libmedia_tv_tuner",
+    srcs: [
+        "android_media_tv_Tuner.cpp",
+    ],
+
+    shared_libs: [
+        "android.hardware.tv.tuner@1.0",
+        "libandroid_runtime",
+        "liblog",
+        "libutils",
+    ],
+
+    export_include_dirs: ["."],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+}
+
 subdirs = [
     "audioeffect",
     "soundpool",
diff --git a/media/jni/JetPlayer.cpp b/media/jni/JetPlayer.cpp
new file mode 100644
index 0000000..358feb7
--- /dev/null
+++ b/media/jni/JetPlayer.cpp
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "JetPlayer-C"
+
+#include <utils/Log.h>
+#include "JetPlayer.h"
+
+
+namespace android
+{
+
+static const int MIX_NUM_BUFFERS = 4;
+static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::JetPlayer(void *javaJetPlayer, int maxTracks, int trackBufferSize) :
+        mEventCallback(NULL),
+        mJavaJetPlayerRef(javaJetPlayer),
+        mTid(-1),
+        mRender(false),
+        mPaused(false),
+        mMaxTracks(maxTracks),
+        mEasData(NULL),
+        mIoWrapper(NULL),
+        mTrackBufferSize(trackBufferSize)
+{
+    ALOGV("JetPlayer constructor");
+    mPreviousJetStatus.currentUserID = -1;
+    mPreviousJetStatus.segmentRepeatCount = -1;
+    mPreviousJetStatus.numQueuedSegments = -1;
+    mPreviousJetStatus.paused = true;
+}
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::~JetPlayer()
+{
+    ALOGV("~JetPlayer");
+    release();
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::init()
+{
+    //Mutex::Autolock lock(&mMutex);
+
+    EAS_RESULT result;
+
+    // retrieve the EAS library settings
+    if (pLibConfig == NULL)
+        pLibConfig = EAS_Config();
+    if (pLibConfig == NULL) {
+        ALOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
+        return EAS_FAILURE;
+    }
+
+    // init the EAS library
+    result = EAS_Init(&mEasData);
+    if (result != EAS_SUCCESS) {
+        ALOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
+        mState = EAS_STATE_ERROR;
+        return result;
+    }
+    // init the JET library with the default app event controller range
+    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
+    if (result != EAS_SUCCESS) {
+        ALOGE("JetPlayer::init(): Error initializing JET library, aborting.");
+        mState = EAS_STATE_ERROR;
+        return result;
+    }
+
+    // create the output AudioTrack
+    mAudioTrack = new AudioTrack();
+    status_t status = mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parameterize this
+            pLibConfig->sampleRate,
+            AUDIO_FORMAT_PCM_16_BIT,
+            audio_channel_out_mask_from_count(pLibConfig->numChannels),
+            (size_t) mTrackBufferSize,
+            AUDIO_OUTPUT_FLAG_NONE);
+    if (status != OK) {
+        ALOGE("JetPlayer::init(): Error initializing JET library; AudioTrack error %d", status);
+        mAudioTrack.clear();
+        mState = EAS_STATE_ERROR;
+        return EAS_FAILURE;
+    }
+
+    // create render and playback thread
+    {
+        Mutex::Autolock l(mMutex);
+        ALOGV("JetPlayer::init(): trying to start render thread");
+        mThread = new JetPlayerThread(this);
+        mThread->run("jetRenderThread", ANDROID_PRIORITY_AUDIO);
+        mCondition.wait(mMutex);
+    }
+    if (mTid > 0) {
+        // render thread started, we're ready
+        ALOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
+        mState = EAS_STATE_READY;
+    } else {
+        ALOGE("JetPlayer::init(): failed to start render thread.");
+        mState = EAS_STATE_ERROR;
+        return EAS_FAILURE;
+    }
+
+    return EAS_SUCCESS;
+}
+
+void JetPlayer::setEventCallback(jetevent_callback eventCallback)
+{
+    Mutex::Autolock l(mMutex);
+    mEventCallback = eventCallback;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::release()
+{
+    ALOGV("JetPlayer::release()");
+    Mutex::Autolock lock(mMutex);
+    mPaused = true;
+    mRender = false;
+    if (mEasData) {
+        JET_Pause(mEasData);
+        JET_CloseFile(mEasData);
+        JET_Shutdown(mEasData);
+        EAS_Shutdown(mEasData);
+    }
+    delete mIoWrapper;
+    mIoWrapper = NULL;
+    if (mAudioTrack != 0) {
+        mAudioTrack->stop();
+        mAudioTrack->flush();
+        mAudioTrack.clear();
+    }
+    if (mAudioBuffer) {
+        delete mAudioBuffer;
+        mAudioBuffer = NULL;
+    }
+    mEasData = NULL;
+
+    return EAS_SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::render() {
+    EAS_RESULT result = EAS_FAILURE;
+    EAS_I32 count;
+    int temp;
+    bool audioStarted = false;
+
+    ALOGV("JetPlayer::render(): entering");
+
+    // allocate render buffer
+    mAudioBuffer =
+        new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS];
+
+    // signal main thread that we started
+    {
+        Mutex::Autolock l(mMutex);
+        mTid = gettid();
+        ALOGV("JetPlayer::render(): render thread(%d) signal", mTid);
+        mCondition.signal();
+    }
+
+    while (1) {
+
+        mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
+
+        if (mEasData == NULL) {
+            mMutex.unlock();
+            ALOGV("JetPlayer::render(): NULL EAS data, exiting render.");
+            goto threadExit;
+        }
+
+        // nothing to render, wait for client thread to wake us up
+        while (!mRender)
+        {
+            ALOGV("JetPlayer::render(): signal wait");
+            if (audioStarted) {
+                mAudioTrack->pause();
+                // we have to restart the playback once we start rendering again
+                audioStarted = false;
+            }
+            mCondition.wait(mMutex);
+            ALOGV("JetPlayer::render(): signal rx'd");
+        }
+
+        // render midi data into the input buffer
+        int num_output = 0;
+        EAS_PCM* p = mAudioBuffer;
+        for (int i = 0; i < MIX_NUM_BUFFERS; i++) {
+            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
+            if (result != EAS_SUCCESS) {
+                ALOGE("JetPlayer::render(): EAS_Render returned error %ld", result);
+            }
+            p += count * pLibConfig->numChannels;
+            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
+
+            // send events that were generated (if any) to the event callback
+            fireEventsFromJetQueue();
+        }
+
+        // update playback state
+        //ALOGV("JetPlayer::render(): updating state");
+        JET_Status(mEasData, &mJetStatus);
+        fireUpdateOnStatusChange();
+        mPaused = mJetStatus.paused;
+
+        mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------
+
+        // check audio output track
+        if (mAudioTrack == NULL) {
+            ALOGE("JetPlayer::render(): output AudioTrack was not created");
+            goto threadExit;
+        }
+
+        // Write data to the audio hardware
+        //ALOGV("JetPlayer::render(): writing to audio output");
+        if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) {
+            ALOGE("JetPlayer::render(): Error in writing:%d",temp);
+            return temp;
+        }
+
+        // start audio output if necessary
+        if (!audioStarted) {
+            ALOGV("JetPlayer::render(): starting audio playback");
+            mAudioTrack->start();
+            audioStarted = true;
+        }
+
+    }//while (1)
+
+threadExit:
+    if (mAudioTrack != NULL) {
+        mAudioTrack->stop();
+        mAudioTrack->flush();
+    }
+    delete [] mAudioBuffer;
+    mAudioBuffer = NULL;
+    mMutex.lock();
+    mTid = -1;
+    mCondition.signal();
+    mMutex.unlock();
+    return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up an update if any of the status fields has changed
+// precondition: mMutex locked
+void JetPlayer::fireUpdateOnStatusChange()
+{
+    if ( (mJetStatus.currentUserID      != mPreviousJetStatus.currentUserID)
+       ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
+        if (mEventCallback)  {
+            mEventCallback(
+                JetPlayer::JET_USERID_UPDATE,
+                mJetStatus.currentUserID,
+                mJetStatus.segmentRepeatCount,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.currentUserID      = mJetStatus.currentUserID;
+        mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount;
+    }
+
+    if (mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) {
+        if (mEventCallback)  {
+            mEventCallback(
+                JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE,
+                mJetStatus.numQueuedSegments,
+                -1,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.numQueuedSegments  = mJetStatus.numQueuedSegments;
+    }
+
+    if (mJetStatus.paused != mPreviousJetStatus.paused) {
+        if (mEventCallback)  {
+            mEventCallback(JetPlayer::JET_PAUSE_UPDATE,
+                mJetStatus.paused,
+                -1,
+                mJavaJetPlayerRef);
+        }
+        mPreviousJetStatus.paused = mJetStatus.paused;
+    }
+
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up all the JET events in the JET engine queue (until the queue is empty)
+// precondition: mMutex locked
+void JetPlayer::fireEventsFromJetQueue()
+{
+    if (!mEventCallback) {
+        // no callback, just empty the event queue
+        while (JET_GetEvent(mEasData, NULL, NULL)) { }
+        return;
+    }
+
+    EAS_U32 rawEvent;
+    while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
+        mEventCallback(
+            JetPlayer::JET_EVENT,
+            rawEvent,
+            -1,
+            mJavaJetPlayerRef);
+    }
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFile(const char* path)
+{
+    ALOGV("JetPlayer::loadFromFile(): path=%s", path);
+
+    Mutex::Autolock lock(mMutex);
+
+    delete mIoWrapper;
+    mIoWrapper = new MidiIoWrapper(path);
+
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
+    if (result != EAS_SUCCESS)
+        mState = EAS_STATE_ERROR;
+    else
+        mState = EAS_STATE_OPEN;
+    return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
+{
+    ALOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);
+
+    Mutex::Autolock lock(mMutex);
+
+    delete mIoWrapper;
+    mIoWrapper = new MidiIoWrapper(fd, offset, length);
+
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
+    if (result != EAS_SUCCESS)
+        mState = EAS_STATE_ERROR;
+    else
+        mState = EAS_STATE_OPEN;
+    return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::closeFile()
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_CloseFile(mEasData);
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::play()
+{
+    ALOGV("JetPlayer::play(): entering");
+    Mutex::Autolock lock(mMutex);
+
+    EAS_RESULT result = JET_Play(mEasData);
+
+    mPaused = false;
+    mRender = true;
+
+    JET_Status(mEasData, &mJetStatus);
+    this->dumpJetStatus(&mJetStatus);
+
+    fireUpdateOnStatusChange();
+
+    // wake up render thread
+    ALOGV("JetPlayer::play(): wakeup render thread");
+    mCondition.signal();
+
+    return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::pause()
+{
+    Mutex::Autolock lock(mMutex);
+    mPaused = true;
+    EAS_RESULT result = JET_Pause(mEasData);
+
+    mRender = false;
+
+    JET_Status(mEasData, &mJetStatus);
+    this->dumpJetStatus(&mJetStatus);
+    fireUpdateOnStatusChange();
+
+
+    return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
+        EAS_U32 muteFlags, EAS_U8 userID)
+{
+    ALOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
+        segmentNum, libNum, repeatCount, transpose);
+    Mutex::Autolock lock(mMutex);
+    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags,
+            userID);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync)
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_SetMuteFlags(mEasData, muteFlags, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync)
+{
+    Mutex::Autolock lock(mMutex);
+    return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::triggerClip(int clipId)
+{
+    ALOGV("JetPlayer::triggerClip clipId=%d", clipId);
+    Mutex::Autolock lock(mMutex);
+    return JET_TriggerClip(mEasData, clipId);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::clearQueue()
+{
+    ALOGV("JetPlayer::clearQueue");
+    Mutex::Autolock lock(mMutex);
+    return JET_Clear_Queue(mEasData);
+}
+
+//-------------------------------------------------------------------------------------------------
+void JetPlayer::dump()
+{
+}
+
+void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
+{
+    if (pJetStatus!=NULL)
+        ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d "
+                "paused=%d",
+                pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
+                pJetStatus->numQueuedSegments, pJetStatus->paused);
+    else
+        ALOGE(">> JET player status is NULL");
+}
+
+
+} // end namespace android
diff --git a/media/jni/JetPlayer.h b/media/jni/JetPlayer.h
new file mode 100644
index 0000000..bb569bc
--- /dev/null
+++ b/media/jni/JetPlayer.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef JETPLAYER_H_
+#define JETPLAYER_H_
+
+#include <utils/threads.h>
+
+#include <libsonivox/jet.h>
+#include <libsonivox/eas_types.h>
+#include <media/AudioTrack.h>
+#include <media/MidiIoWrapper.h>
+
+
+namespace android {
+
+typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie);
+
+class JetPlayer {
+
+public:
+
+    // to keep in sync with the JetPlayer class constants
+    // defined in frameworks/base/media/java/android/media/JetPlayer.java
+    static const int JET_EVENT                   = 1;
+    static const int JET_USERID_UPDATE           = 2;
+    static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
+    static const int JET_PAUSE_UPDATE            = 4;
+
+    JetPlayer(void *javaJetPlayer,
+            int maxTracks = 32,
+            int trackBufferSize = 1200);
+    ~JetPlayer();
+    int init();
+    int release();
+
+    int loadFromFile(const char* url);
+    int loadFromFD(const int fd, const long long offset, const long long length);
+    int closeFile();
+    int play();
+    int pause();
+    int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
+            EAS_U32 muteFlags, EAS_U8 userID);
+    int setMuteFlags(EAS_U32 muteFlags, bool sync);
+    int setMuteFlag(int trackNum, bool muteFlag, bool sync);
+    int triggerClip(int clipId);
+    int clearQueue();
+
+    void setEventCallback(jetevent_callback callback);
+
+    int getMaxTracks() { return mMaxTracks; };
+
+
+private:
+    int                 render();
+    void                fireUpdateOnStatusChange();
+    void                fireEventsFromJetQueue();
+
+    JetPlayer() {} // no default constructor
+    void dump();
+    void dumpJetStatus(S_JET_STATUS* pJetStatus);
+
+    jetevent_callback   mEventCallback;
+
+    void*               mJavaJetPlayerRef;
+    Mutex               mMutex; // mutex to sync the render and playback thread with the JET calls
+    pid_t               mTid;
+    Condition           mCondition;
+    volatile bool       mRender;
+    bool                mPaused;
+
+    EAS_STATE           mState;
+    int*                mMemFailedVar;
+
+    int                 mMaxTracks; // max number of MIDI tracks, usually 32
+    EAS_DATA_HANDLE     mEasData;
+    MidiIoWrapper*      mIoWrapper;
+    EAS_PCM*            mAudioBuffer;// EAS renders the MIDI data into this buffer,
+    sp<AudioTrack>      mAudioTrack; // and we play it in this audio track
+    int                 mTrackBufferSize;
+    S_JET_STATUS        mJetStatus;
+    S_JET_STATUS        mPreviousJetStatus;
+
+    class JetPlayerThread : public Thread {
+    public:
+        JetPlayerThread(JetPlayer *player) : mPlayer(player) {
+        }
+
+    protected:
+        virtual ~JetPlayerThread() {}
+
+    private:
+        JetPlayer *mPlayer;
+
+        bool threadLoop() {
+            int result;
+            result = mPlayer->render();
+            return false;
+        }
+
+        JetPlayerThread(const JetPlayerThread &);
+        JetPlayerThread &operator=(const JetPlayerThread &);
+    };
+
+    sp<JetPlayerThread> mThread;
+
+}; // end class JetPlayer
+
+} // end namespace android
+
+
+
+#endif /*JETPLAYER_H_*/
diff --git a/core/jni/android_media_JetPlayer.cpp b/media/jni/android_media_JetPlayer.cpp
similarity index 99%
rename from core/jni/android_media_JetPlayer.cpp
rename to media/jni/android_media_JetPlayer.cpp
index da116bf..8a05f85 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/media/jni/android_media_JetPlayer.cpp
@@ -27,7 +27,7 @@
 #include "core_jni_helpers.h"
 
 #include <utils/Log.h>
-#include <media/JetPlayer.h>
+#include "JetPlayer.h"
 
 
 using namespace android;
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 94299bc..b4fa07b 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1436,6 +1436,7 @@
 }
 extern int register_android_media_ImageReader(JNIEnv *env);
 extern int register_android_media_ImageWriter(JNIEnv *env);
+extern int register_android_media_JetPlayer(JNIEnv *env);
 extern int register_android_media_Crypto(JNIEnv *env);
 extern int register_android_media_Drm(JNIEnv *env);
 extern int register_android_media_Descrambler(JNIEnv *env);
@@ -1474,6 +1475,11 @@
         goto bail;
     }
 
+    if (register_android_media_JetPlayer(env) < 0) {
+        ALOGE("ERROR: JetPlayer native registration failed");
+        goto bail;
+    }
+
     if (register_android_media_MediaPlayer(env) < 0) {
         ALOGE("ERROR: MediaPlayer native registration failed\n");
         goto bail;
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
new file mode 100644
index 0000000..d499eee
--- /dev/null
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "TvTuner-JNI"
+#include <utils/Log.h>
+
+#include "android_media_tv_Tuner.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+using ::android::hardware::tv::tuner::V1_0::ITuner;
+
+struct fields_t {
+    jfieldID context;
+};
+
+static fields_t gFields;
+
+namespace android {
+
+sp<ITuner> JTuner::mTuner;
+
+JTuner::JTuner(JNIEnv *env, jobject thiz)
+    : mClass(NULL) {
+    jclass clazz = env->GetObjectClass(thiz);
+    CHECK(clazz != NULL);
+
+    mClass = (jclass)env->NewGlobalRef(clazz);
+    mObject = env->NewWeakGlobalRef(thiz);
+    if (mTuner == NULL) {
+        mTuner = getTunerService();
+    }
+}
+
+JTuner::~JTuner() {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    env->DeleteGlobalRef(mClass);
+    mTuner = NULL;
+    mClass = NULL;
+    mObject = NULL;
+}
+
+sp<ITuner> JTuner::getTunerService() {
+    if (mTuner == nullptr) {
+        mTuner = ITuner::getService();
+
+        if (mTuner == nullptr) {
+            ALOGW("Failed to get tuner service.");
+        }
+    }
+    return mTuner;
+}
+
+}  // namespace android
+
+////////////////////////////////////////////////////////////////////////////////
+
+using namespace android;
+
+static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) {
+    sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.context);
+
+    if (tuner != NULL) {
+        tuner->incStrong(thiz);
+    }
+    if (old != NULL) {
+        old->decStrong(thiz);
+    }
+    env->SetLongField(thiz, gFields.context, (jlong)tuner.get());
+
+    return old;
+}
+
+static sp<JTuner> getTuner(JNIEnv *env, jobject thiz) {
+    return (JTuner *)env->GetLongField(thiz, gFields.context);
+}
+
+static void android_media_tv_Tuner_native_init(JNIEnv *env) {
+    jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+    CHECK(clazz != NULL);
+
+    gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
+    CHECK(gFields.context != NULL);
+}
+
+static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
+    sp<JTuner> tuner = new JTuner(env, thiz);
+    setTuner(env,thiz, tuner);
+}
+
+static const JNINativeMethod gMethods[] = {
+    { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
+    { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
+};
+
+static int register_android_media_tv_Tuner(JNIEnv *env) {
+    return AndroidRuntime::registerNativeMethods(
+            env, "android/media/tv/tuner/Tuner", gMethods, NELEM(gMethods));
+}
+
+jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        ALOGE("ERROR: GetEnv failed\n");
+        return result;
+    }
+    assert(env != NULL);
+
+    if (register_android_media_tv_Tuner(env) != JNI_OK) {
+        ALOGE("ERROR: Tuner native registration failed\n");
+        return result;
+    }
+    return JNI_VERSION_1_4;
+}
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
new file mode 100644
index 0000000..e7d5924
--- /dev/null
+++ b/media/jni/android_media_tv_Tuner.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_TV_TUNER_H_
+#define _ANDROID_MEDIA_TV_TUNER_H_
+
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <utils/RefBase.h>
+
+#include "jni.h"
+
+using ::android::hardware::tv::tuner::V1_0::ITuner;
+
+namespace android {
+
+struct JTuner : public RefBase {
+    JTuner(JNIEnv *env, jobject thiz);
+    sp<ITuner> getTunerService();
+protected:
+    virtual ~JTuner();
+
+private:
+    jclass mClass;
+    jweak mObject;
+    static sp<ITuner> mTuner;
+};
+
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_TUNER_H_
diff --git a/media/jni/audioeffect/Android.bp b/media/jni/audioeffect/Android.bp
index 09c546a..41ab670 100644
--- a/media/jni/audioeffect/Android.bp
+++ b/media/jni/audioeffect/Android.bp
@@ -6,6 +6,7 @@
         "android_media_SourceDefaultEffect.cpp",
         "android_media_StreamDefaultEffect.cpp",
         "android_media_Visualizer.cpp",
+        "Visualizer.cpp",
     ],
 
     shared_libs: [
@@ -14,10 +15,12 @@
         "libutils",
         "libandroid_runtime",
         "libnativehelper",
-        "libmedia",
         "libaudioclient",
+        "libaudioutils",
     ],
 
+    version_script: "exports.lds",
+
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/media/jni/audioeffect/Visualizer.cpp b/media/jni/audioeffect/Visualizer.cpp
new file mode 100644
index 0000000..e48032a
--- /dev/null
+++ b/media/jni/audioeffect/Visualizer.cpp
@@ -0,0 +1,443 @@
+/*
+**
+** Copyright 2010, 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.
+*/
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Visualizer"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <audio_utils/fixedfft.h>
+#include <utils/Thread.h>
+
+#include "Visualizer.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+Visualizer::Visualizer (const String16& opPackageName,
+         int32_t priority,
+         effect_callback_t cbf,
+         void* user,
+         audio_session_t sessionId)
+    :   AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId),
+        mCaptureRate(CAPTURE_RATE_DEF),
+        mCaptureSize(CAPTURE_SIZE_DEF),
+        mSampleRate(44100000),
+        mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
+        mMeasurementMode(MEASUREMENT_MODE_NONE),
+        mCaptureCallBack(NULL),
+        mCaptureCbkUser(NULL)
+{
+    initCaptureSize();
+}
+
+Visualizer::~Visualizer()
+{
+    ALOGV("Visualizer::~Visualizer()");
+    setEnabled(false);
+    setCaptureCallBack(NULL, NULL, 0, 0);
+}
+
+void Visualizer::release()
+{
+    ALOGV("Visualizer::release()");
+    setEnabled(false);
+    Mutex::Autolock _l(mCaptureLock);
+
+    mCaptureThread.clear();
+    mCaptureCallBack = NULL;
+    mCaptureCbkUser = NULL;
+    mCaptureFlags = 0;
+    mCaptureRate = 0;
+}
+
+status_t Visualizer::setEnabled(bool enabled)
+{
+    Mutex::Autolock _l(mCaptureLock);
+
+    sp<CaptureThread> t = mCaptureThread;
+    if (t != 0) {
+        if (enabled) {
+            if (t->exitPending()) {
+                if (t->requestExitAndWait() == WOULD_BLOCK) {
+                    ALOGE("Visualizer::enable() called from thread");
+                    return INVALID_OPERATION;
+                }
+            }
+        }
+        t->mLock.lock();
+    }
+
+    status_t status = AudioEffect::setEnabled(enabled);
+
+    if (t != 0) {
+        if (enabled && status == NO_ERROR) {
+            t->run("Visualizer");
+        } else {
+            t->requestExit();
+        }
+    }
+
+    if (t != 0) {
+        t->mLock.unlock();
+    }
+
+    return status;
+}
+
+status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags,
+        uint32_t rate)
+{
+    if (rate > CAPTURE_RATE_MAX) {
+        return BAD_VALUE;
+    }
+    Mutex::Autolock _l(mCaptureLock);
+
+    if (mEnabled) {
+        return INVALID_OPERATION;
+    }
+
+    if (mCaptureThread != 0) {
+        mCaptureLock.unlock();
+        mCaptureThread->requestExitAndWait();
+        mCaptureLock.lock();
+    }
+
+    mCaptureThread.clear();
+    mCaptureCallBack = cbk;
+    mCaptureCbkUser = user;
+    mCaptureFlags = flags;
+    mCaptureRate = rate;
+
+    if (cbk != NULL) {
+        mCaptureThread = new CaptureThread(this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
+    }
+    ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
+            rate, mCaptureThread.get(), mCaptureFlags);
+    return NO_ERROR;
+}
+
+status_t Visualizer::setCaptureSize(uint32_t size)
+{
+    if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
+        size < VISUALIZER_CAPTURE_SIZE_MIN ||
+        popcount(size) != 1) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mCaptureLock);
+    if (mEnabled) {
+        return INVALID_OPERATION;
+    }
+
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
+    *((int32_t *)p->data + 1)= size;
+    status_t status = setParameter(p);
+
+    ALOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status);
+
+    if (status == NO_ERROR) {
+        status = p->status;
+        if (status == NO_ERROR) {
+            mCaptureSize = size;
+        }
+    }
+
+    return status;
+}
+
+status_t Visualizer::setScalingMode(uint32_t mode) {
+    if ((mode != VISUALIZER_SCALING_MODE_NORMALIZED)
+            && (mode != VISUALIZER_SCALING_MODE_AS_PLAYED)) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mCaptureLock);
+
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISUALIZER_PARAM_SCALING_MODE;
+    *((int32_t *)p->data + 1)= mode;
+    status_t status = setParameter(p);
+
+    ALOGV("setScalingMode mode %d  status %d p->status %d", mode, status, p->status);
+
+    if (status == NO_ERROR) {
+        status = p->status;
+        if (status == NO_ERROR) {
+            mScalingMode = mode;
+        }
+    }
+
+    return status;
+}
+
+status_t Visualizer::setMeasurementMode(uint32_t mode) {
+    if ((mode != MEASUREMENT_MODE_NONE)
+            //Note: needs to be handled as a mask when more measurement modes are added
+            && ((mode & MEASUREMENT_MODE_PEAK_RMS) != mode)) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mCaptureLock);
+
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
+    *((int32_t *)p->data + 1)= mode;
+    status_t status = setParameter(p);
+
+    ALOGV("setMeasurementMode mode %d  status %d p->status %d", mode, status, p->status);
+
+    if (status == NO_ERROR) {
+        status = p->status;
+        if (status == NO_ERROR) {
+            mMeasurementMode = mode;
+        }
+    }
+    return status;
+}
+
+status_t Visualizer::getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements) {
+    if (mMeasurementMode == MEASUREMENT_MODE_NONE) {
+        ALOGE("Cannot retrieve int measurements, no measurement mode set");
+        return INVALID_OPERATION;
+    }
+    if (!(mMeasurementMode & type)) {
+        // measurement type has not been set on this Visualizer
+        ALOGE("Cannot retrieve int measurements, requested measurement mode 0x%x not set(0x%x)",
+                type, mMeasurementMode);
+        return INVALID_OPERATION;
+    }
+    // only peak+RMS measurement supported
+    if ((type != MEASUREMENT_MODE_PEAK_RMS)
+            // for peak+RMS measurement, the results are 2 int32_t values
+            || (number != 2)) {
+        ALOGE("Cannot retrieve int measurements, MEASUREMENT_MODE_PEAK_RMS returns 2 ints, not %d",
+                        number);
+        return BAD_VALUE;
+    }
+
+    status_t status = NO_ERROR;
+    if (mEnabled) {
+        uint32_t replySize = number * sizeof(int32_t);
+        status = command(VISUALIZER_CMD_MEASURE,
+                sizeof(uint32_t)  /*cmdSize*/,
+                &type /*cmdData*/,
+                &replySize, measurements);
+        ALOGV("getMeasurements() command returned %d", status);
+        if ((status == NO_ERROR) && (replySize == 0)) {
+            status = NOT_ENOUGH_DATA;
+        }
+    } else {
+        ALOGV("getMeasurements() disabled");
+        return INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t Visualizer::getWaveForm(uint8_t *waveform)
+{
+    if (waveform == NULL) {
+        return BAD_VALUE;
+    }
+    if (mCaptureSize == 0) {
+        return NO_INIT;
+    }
+
+    status_t status = NO_ERROR;
+    if (mEnabled) {
+        uint32_t replySize = mCaptureSize;
+        status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
+        ALOGV("getWaveForm() command returned %d", status);
+        if ((status == NO_ERROR) && (replySize == 0)) {
+            status = NOT_ENOUGH_DATA;
+        }
+    } else {
+        ALOGV("getWaveForm() disabled");
+        memset(waveform, 0x80, mCaptureSize);
+    }
+    return status;
+}
+
+status_t Visualizer::getFft(uint8_t *fft)
+{
+    if (fft == NULL) {
+        return BAD_VALUE;
+    }
+    if (mCaptureSize == 0) {
+        return NO_INIT;
+    }
+
+    status_t status = NO_ERROR;
+    if (mEnabled) {
+        uint8_t buf[mCaptureSize];
+        status = getWaveForm(buf);
+        if (status == NO_ERROR) {
+            status = doFft(fft, buf);
+        }
+    } else {
+        memset(fft, 0, mCaptureSize);
+    }
+    return status;
+}
+
+status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
+{
+    int32_t workspace[mCaptureSize >> 1];
+    int32_t nonzero = 0;
+
+    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+        workspace[i >> 1] =
+                ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8);
+        nonzero |= workspace[i >> 1];
+    }
+
+    if (nonzero) {
+        fixed_fft_real(mCaptureSize >> 1, workspace);
+    }
+
+    for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+        short tmp = workspace[i >> 1] >> 21;
+        while (tmp > 127 || tmp < -128) tmp >>= 1;
+        fft[i] = tmp;
+        tmp = workspace[i >> 1];
+        tmp >>= 5;
+        while (tmp > 127 || tmp < -128) tmp >>= 1;
+        fft[i + 1] = tmp;
+    }
+
+    return NO_ERROR;
+}
+
+void Visualizer::periodicCapture()
+{
+    Mutex::Autolock _l(mCaptureLock);
+    ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
+            this, mCaptureCallBack, mCaptureFlags);
+    if (mCaptureCallBack != NULL &&
+        (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
+        mCaptureSize != 0) {
+        uint8_t waveform[mCaptureSize];
+        status_t status = getWaveForm(waveform);
+        if (status != NO_ERROR) {
+            return;
+        }
+        uint8_t fft[mCaptureSize];
+        if (mCaptureFlags & CAPTURE_FFT) {
+            status = doFft(fft, waveform);
+        }
+        if (status != NO_ERROR) {
+            return;
+        }
+        uint8_t *wavePtr = NULL;
+        uint8_t *fftPtr = NULL;
+        uint32_t waveSize = 0;
+        uint32_t fftSize = 0;
+        if (mCaptureFlags & CAPTURE_WAVEFORM) {
+            wavePtr = waveform;
+            waveSize = mCaptureSize;
+        }
+        if (mCaptureFlags & CAPTURE_FFT) {
+            fftPtr = fft;
+            fftSize = mCaptureSize;
+        }
+        mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
+    }
+}
+
+uint32_t Visualizer::initCaptureSize()
+{
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE;
+    status_t status = getParameter(p);
+
+    if (status == NO_ERROR) {
+        status = p->status;
+    }
+
+    uint32_t size = 0;
+    if (status == NO_ERROR) {
+        size = *((int32_t *)p->data + 1);
+    }
+    mCaptureSize = size;
+
+    ALOGV("initCaptureSize size %d status %d", mCaptureSize, status);
+
+    return size;
+}
+
+void Visualizer::controlStatusChanged(bool controlGranted) {
+    if (controlGranted) {
+        // this Visualizer instance regained control of the effect, reset the scaling mode
+        //   and capture size as has been cached through it.
+        ALOGV("controlStatusChanged(true) causes effect parameter reset:");
+        ALOGV("    scaling mode reset to %d", mScalingMode);
+        setScalingMode(mScalingMode);
+        ALOGV("    capture size reset to %d", mCaptureSize);
+        setCaptureSize(mCaptureSize);
+    }
+    AudioEffect::controlStatusChanged(controlGranted);
+}
+
+//-------------------------------------------------------------------------
+
+Visualizer::CaptureThread::CaptureThread(Visualizer* receiver, uint32_t captureRate,
+        bool bCanCallJava)
+    : Thread(bCanCallJava), mReceiver(receiver)
+{
+    mSleepTimeUs = 1000000000 / captureRate;
+    ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
+}
+
+bool Visualizer::CaptureThread::threadLoop()
+{
+    ALOGV("CaptureThread %p enter", this);
+    sp<Visualizer> receiver = mReceiver.promote();
+    if (receiver == NULL) {
+        return false;
+    }
+    while (!exitPending())
+    {
+        usleep(mSleepTimeUs);
+        receiver->periodicCapture();
+    }
+    ALOGV("CaptureThread %p exiting", this);
+    return false;
+}
+
+} // namespace android
diff --git a/media/jni/audioeffect/Visualizer.h b/media/jni/audioeffect/Visualizer.h
new file mode 100644
index 0000000..8078e36
--- /dev/null
+++ b/media/jni/audioeffect/Visualizer.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_MEDIA_VISUALIZER_H
+#define ANDROID_MEDIA_VISUALIZER_H
+
+#include <media/AudioEffect.h>
+#include <system/audio_effects/effect_visualizer.h>
+#include <utils/Thread.h>
+
+/**
+ * The Visualizer class enables application to retrieve part of the currently playing audio for
+ * visualization purpose. It is not an audio recording interface and only returns partial and low
+ * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
+ * of the visualizer requires the permission android.permission.RECORD_AUDIO.
+ * The audio session ID passed to the constructor indicates which audio content should be
+ * visualized:
+ * - If the session is 0, the audio output mix is visualized
+ * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack
+ *   using this audio session is visualized
+ * Two types of representation of audio content can be captured:
+ * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method
+ * - Frequency data: 8-bit magnitude FFT by using the getFft() method
+ *
+ * The length of the capture can be retrieved or specified by calling respectively
+ * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT
+ * is half of the specified capture size but both sides of the spectrum are returned yielding in a
+ * number of bytes equal to the capture size. The capture size must be a power of 2 in the range
+ * returned by getMinCaptureSize() and getMaxCaptureSize().
+ * In addition to the polling capture mode, a callback mode is also available by installing a
+ * callback function by use of the setCaptureCallBack() method. The rate at which the callback
+ * is called as well as the type of data returned is specified.
+ * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method.
+ * When data capture is not needed any more, the Visualizer should be disabled.
+ */
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class Visualizer: public AudioEffect {
+public:
+
+    enum callback_flags {
+        CAPTURE_WAVEFORM = 0x00000001,  // capture callback returns a PCM wave form
+        CAPTURE_FFT = 0x00000002,       // apture callback returns a frequency representation
+        CAPTURE_CALL_JAVA = 0x00000004  // the callback thread can call java
+    };
+
+
+    /* Constructor.
+     * See AudioEffect constructor for details on parameters.
+     */
+                        Visualizer(const String16& opPackageName,
+                                   int32_t priority = 0,
+                                   effect_callback_t cbf = NULL,
+                                   void* user = NULL,
+                                   audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX);
+
+                        ~Visualizer();
+
+    virtual status_t    setEnabled(bool enabled);
+
+    // maximum capture size in samples
+    static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; }
+    // minimum capture size in samples
+    static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; }
+    // maximum capture rate in millihertz
+    static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; }
+
+    // callback used to return periodic PCM or FFT captures to the application. Either one or both
+    // types of data are returned (PCM and FFT) according to flags indicated when installing the
+    // callback. When a type of data is not present, the corresponding size (waveformSize or
+    // fftSize) is 0.
+    typedef void (*capture_cbk_t)(void* user,
+                                    uint32_t waveformSize,
+                                    uint8_t *waveform,
+                                    uint32_t fftSize,
+                                    uint8_t *fft,
+                                    uint32_t samplingrate);
+
+    // install a callback to receive periodic captures. The capture rate is specified in milliHertz
+    // and the capture format is according to flags  (see callback_flags).
+    status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate);
+
+    // set the capture size capture size must be a power of two in the range
+    // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN]
+    // must be called when the visualizer is not enabled
+    status_t setCaptureSize(uint32_t size);
+    uint32_t getCaptureSize() { return mCaptureSize; }
+
+    // returns the capture rate indicated when installing the callback
+    uint32_t getCaptureRate() { return mCaptureRate; }
+
+    // returns the sampling rate of the audio being captured
+    uint32_t getSamplingRate() { return mSampleRate; }
+
+    // set the way volume affects the captured data
+    // mode must one of VISUALIZER_SCALING_MODE_NORMALIZED,
+    //  VISUALIZER_SCALING_MODE_AS_PLAYED
+    status_t setScalingMode(uint32_t mode);
+    uint32_t getScalingMode() { return mScalingMode; }
+
+    // set which measurements are done on the audio buffers processed by the effect.
+    // valid measurements (mask): MEASUREMENT_MODE_PEAK_RMS
+    status_t setMeasurementMode(uint32_t mode);
+    uint32_t getMeasurementMode() { return mMeasurementMode; }
+
+    // return a set of int32_t measurements
+    status_t getIntMeasurements(uint32_t type, uint32_t number, int32_t *measurements);
+
+    // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
+    // getCaptureSize()
+    status_t getWaveForm(uint8_t *waveform);
+
+    // return a capture in FFT 8 bit signed format. The size of the capture is equal to
+    // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum
+    // are returned
+    status_t getFft(uint8_t *fft);
+    void release();
+
+protected:
+    // from IEffectClient
+    virtual void controlStatusChanged(bool controlGranted);
+
+private:
+
+    static const uint32_t CAPTURE_RATE_MAX = 20000;
+    static const uint32_t CAPTURE_RATE_DEF = 10000;
+    static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX;
+
+    /* internal class to handle the callback */
+    class CaptureThread : public Thread
+    {
+    public:
+        CaptureThread(Visualizer* visualizer, uint32_t captureRate, bool bCanCallJava = false);
+
+    private:
+        friend class Visualizer;
+        virtual bool        threadLoop();
+        wp<Visualizer> mReceiver;
+        Mutex       mLock;
+        uint32_t mSleepTimeUs;
+    };
+
+    status_t doFft(uint8_t *fft, uint8_t *waveform);
+    void periodicCapture();
+    uint32_t initCaptureSize();
+
+    Mutex mCaptureLock;
+    uint32_t mCaptureRate;
+    uint32_t mCaptureSize;
+    uint32_t mSampleRate;
+    uint32_t mScalingMode;
+    uint32_t mMeasurementMode;
+    capture_cbk_t mCaptureCallBack;
+    void *mCaptureCbkUser;
+    sp<CaptureThread> mCaptureThread;
+    uint32_t mCaptureFlags;
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_MEDIA_VISUALIZER_H
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 45de36e..1362433 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -24,7 +24,7 @@
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/threads.h>
-#include "media/Visualizer.h"
+#include "Visualizer.h"
 
 #include <nativehelper/ScopedUtfChars.h>
 
diff --git a/media/jni/audioeffect/exports.lds b/media/jni/audioeffect/exports.lds
new file mode 100644
index 0000000..70491f4
--- /dev/null
+++ b/media/jni/audioeffect/exports.lds
@@ -0,0 +1,6 @@
+{
+    global:
+        *;
+    local:
+        *android10Visualizer*;
+};
diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp
index 35b7b01..e1945dd 100644
--- a/media/jni/soundpool/Android.bp
+++ b/media/jni/soundpool/Android.bp
@@ -3,11 +3,16 @@
 
     srcs: [
         "android_media_SoundPool.cpp",
+        "Sound.cpp",
+        "SoundDecoder.cpp",
+        "SoundManager.cpp",
         "SoundPool.cpp",
-        "SoundPoolThread.cpp",
+        "Stream.cpp",
+        "StreamManager.cpp",
     ],
 
     shared_libs: [
+        "libaudioutils",
         "liblog",
         "libcutils",
         "libutils",
diff --git a/media/jni/soundpool/Sound.cpp b/media/jni/soundpool/Sound.cpp
new file mode 100644
index 0000000..0bbc3e4
--- /dev/null
+++ b/media/jni/soundpool/Sound.cpp
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool::Sound"
+#include <utils/Log.h>
+
+#include "Sound.h"
+
+#include <media/NdkMediaCodec.h>
+#include <media/NdkMediaExtractor.h>
+#include <media/NdkMediaFormat.h>
+
+namespace android::soundpool {
+
+constexpr uint32_t kMaxSampleRate = 192000;
+constexpr size_t   kDefaultHeapSize = 1024 * 1024; // 1MB (compatible with low mem devices)
+
+Sound::Sound(int32_t soundID, int fd, int64_t offset, int64_t length)
+    : mSoundID(soundID)
+    , mFd(dup(fd))
+    , mOffset(offset)
+    , mLength(length)
+{
+    ALOGV("%s(soundID=%d, fd=%d, offset=%lld, length=%lld)",
+            __func__, soundID, fd, (long long)offset, (long long)length);
+    ALOGW_IF(mFd == -1, "Unable to dup descriptor %d", fd);
+}
+
+Sound::~Sound()
+{
+    ALOGV("%s(soundID=%d, fd=%d)", __func__, mSoundID, mFd.get());
+}
+
+static status_t decode(int fd, int64_t offset, int64_t length,
+        uint32_t *rate, int32_t *channelCount, audio_format_t *audioFormat,
+        audio_channel_mask_t *channelMask, sp<MemoryHeapBase> heap,
+        size_t *sizeInBytes) {
+    ALOGV("%s(fd=%d, offset=%lld, length=%lld, ...)",
+            __func__, fd, (long long)offset, (long long)length);
+    std::unique_ptr<AMediaExtractor, decltype(&AMediaExtractor_delete)> ex{
+            AMediaExtractor_new(), &AMediaExtractor_delete};
+    status_t err = AMediaExtractor_setDataSourceFd(ex.get(), fd, offset, length);
+
+    if (err != AMEDIA_OK) {
+        return err;
+    }
+
+    *audioFormat = AUDIO_FORMAT_PCM_16_BIT;  // default format for audio codecs.
+    const size_t numTracks = AMediaExtractor_getTrackCount(ex.get());
+    for (size_t i = 0; i < numTracks; i++) {
+        std::unique_ptr<AMediaFormat, decltype(&AMediaFormat_delete)> format{
+                AMediaExtractor_getTrackFormat(ex.get(), i), &AMediaFormat_delete};
+        const char *mime;
+        if (!AMediaFormat_getString(format.get(),  AMEDIAFORMAT_KEY_MIME, &mime)) {
+            return UNKNOWN_ERROR;
+        }
+        if (strncmp(mime, "audio/", 6) == 0) {
+            std::unique_ptr<AMediaCodec, decltype(&AMediaCodec_delete)> codec{
+                    AMediaCodec_createDecoderByType(mime), &AMediaCodec_delete};
+            if (codec == nullptr
+                    || AMediaCodec_configure(codec.get(), format.get(),
+                            nullptr /* window */, nullptr /* drm */, 0 /* flags */) != AMEDIA_OK
+                    || AMediaCodec_start(codec.get()) != AMEDIA_OK
+                    || AMediaExtractor_selectTrack(ex.get(), i) != AMEDIA_OK) {
+                return UNKNOWN_ERROR;
+            }
+
+            bool sawInputEOS = false;
+            bool sawOutputEOS = false;
+            uint8_t* writePos = static_cast<uint8_t*>(heap->getBase());
+            size_t available = heap->getSize();
+            size_t written = 0;
+            format.reset(AMediaCodec_getOutputFormat(codec.get())); // update format.
+
+            while (!sawOutputEOS) {
+                if (!sawInputEOS) {
+                    ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec.get(), 5000);
+                    ALOGV("%s: input buffer %zd", __func__, bufidx);
+                    if (bufidx >= 0) {
+                        size_t bufsize;
+                        uint8_t * const buf = AMediaCodec_getInputBuffer(
+                                codec.get(), bufidx, &bufsize);
+                        if (buf == nullptr) {
+                            ALOGE("%s: AMediaCodec_getInputBuffer returned nullptr, short decode",
+                                    __func__);
+                            break;
+                        }
+                        int sampleSize = AMediaExtractor_readSampleData(ex.get(), buf, bufsize);
+                        ALOGV("%s: read %d", __func__, sampleSize);
+                        if (sampleSize < 0) {
+                            sampleSize = 0;
+                            sawInputEOS = true;
+                            ALOGV("%s: EOS", __func__);
+                        }
+                        const int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex.get());
+
+                        const media_status_t mstatus = AMediaCodec_queueInputBuffer(
+                                codec.get(), bufidx,
+                                0 /* offset */, sampleSize, presentationTimeUs,
+                                sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
+                        if (mstatus != AMEDIA_OK) {
+                            // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES }
+                            ALOGE("%s: AMediaCodec_queueInputBuffer returned status %d,"
+                                    "short decode",
+                                    __func__, (int)mstatus);
+                            break;
+                        }
+                        (void)AMediaExtractor_advance(ex.get());
+                    }
+                }
+
+                AMediaCodecBufferInfo info;
+                const int status = AMediaCodec_dequeueOutputBuffer(codec.get(), &info, 1);
+                ALOGV("%s: dequeueoutput returned: %d", __func__, status);
+                if (status >= 0) {
+                    if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
+                        ALOGV("%s: output EOS", __func__);
+                        sawOutputEOS = true;
+                    }
+                    ALOGV("%s: got decoded buffer size %d", __func__, info.size);
+
+                    const uint8_t * const buf = AMediaCodec_getOutputBuffer(
+                            codec.get(), status, nullptr /* out_size */);
+                    if (buf == nullptr) {
+                        ALOGE("%s: AMediaCodec_getOutputBuffer returned nullptr, short decode",
+                                __func__);
+                        break;
+                    }
+                    const size_t dataSize = std::min((size_t)info.size, available);
+                    memcpy(writePos, buf + info.offset, dataSize);
+                    writePos += dataSize;
+                    written += dataSize;
+                    available -= dataSize;
+                    const media_status_t mstatus = AMediaCodec_releaseOutputBuffer(
+                            codec.get(), status, false /* render */);
+                    if (mstatus != AMEDIA_OK) {
+                        // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES }
+                        ALOGE("%s: AMediaCodec_releaseOutputBuffer"
+                                " returned status %d, short decode",
+                                __func__, (int)mstatus);
+                        break;
+                    }
+                    if (available == 0) {
+                        // there might be more data, but there's no space for it
+                        sawOutputEOS = true;
+                    }
+                } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
+                    ALOGV("%s: output buffers changed", __func__);
+                } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+                    format.reset(AMediaCodec_getOutputFormat(codec.get())); // update format
+                    ALOGV("%s: format changed to: %s",
+                           __func__, AMediaFormat_toString(format.get()));
+                } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+                    ALOGV("%s: no output buffer right now", __func__);
+                } else if (status <= AMEDIA_ERROR_BASE) {
+                    ALOGE("%s: decode error: %d", __func__, status);
+                    break;
+                } else {
+                    ALOGV("%s: unexpected info code: %d", __func__, status);
+                }
+            }
+
+            (void)AMediaCodec_stop(codec.get());
+            if (!AMediaFormat_getInt32(
+                    format.get(), AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) rate) ||
+                !AMediaFormat_getInt32(
+                    format.get(), AMEDIAFORMAT_KEY_CHANNEL_COUNT, channelCount)) {
+                return UNKNOWN_ERROR;
+            }
+            if (!AMediaFormat_getInt32(format.get(), AMEDIAFORMAT_KEY_CHANNEL_MASK,
+                    (int32_t*) channelMask)) {
+                *channelMask = AUDIO_CHANNEL_NONE;
+            }
+            *sizeInBytes = written;
+            return OK;
+        }
+    }
+    return UNKNOWN_ERROR;
+}
+
+status_t Sound::doLoad()
+{
+    ALOGV("%s()", __func__);
+    status_t status = NO_INIT;
+    if (mFd.get() != -1) {
+        mHeap = new MemoryHeapBase(kDefaultHeapSize);
+
+        ALOGV("%s: start decode", __func__);
+        uint32_t sampleRate;
+        int32_t channelCount;
+        audio_format_t format;
+        audio_channel_mask_t channelMask;
+        status_t status = decode(mFd.get(), mOffset, mLength, &sampleRate, &channelCount, &format,
+                        &channelMask, mHeap, &mSizeInBytes);
+        ALOGV("%s: close(%d)", __func__, mFd.get());
+        mFd.reset();  // close
+
+        if (status != NO_ERROR) {
+            ALOGE("%s: unable to load sound", __func__);
+        } else if (sampleRate > kMaxSampleRate) {
+            ALOGE("%s: sample rate (%u) out of range", __func__, sampleRate);
+            status = BAD_VALUE;
+        } else if (channelCount < 1 || channelCount > FCC_8) {
+            ALOGE("%s: sample channel count (%d) out of range", __func__, channelCount);
+            status = BAD_VALUE;
+        } else {
+            // Correctly loaded, proper parameters
+            ALOGV("%s: pointer = %p, sizeInBytes = %zu, sampleRate = %u, channelCount = %d",
+                  __func__, mHeap->getBase(), mSizeInBytes, sampleRate, channelCount);
+            mData = new MemoryBase(mHeap, 0, mSizeInBytes);
+            mSampleRate = sampleRate;
+            mChannelCount = channelCount;
+            mFormat = format;
+            mChannelMask = channelMask;
+            mState = READY;  // this should be last, as it is an atomic sync point
+            return NO_ERROR;
+        }
+    } else {
+        ALOGE("%s: uninitialized fd, dup failed", __func__);
+    }
+    // ERROR handling
+    mHeap.clear();
+    mState = DECODE_ERROR; // this should be last, as it is an atomic sync point
+    return status;
+}
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/Sound.h b/media/jni/soundpool/Sound.h
new file mode 100644
index 0000000..efe940a
--- /dev/null
+++ b/media/jni/soundpool/Sound.h
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <system/audio.h>
+
+namespace android::soundpool {
+
+class SoundDecoder;
+
+/**
+ * Sound is a resource used by SoundPool, referenced by soundID.
+ *
+ * After loading, it is effectively const so no locking required.
+ * However, in order to guarantee that all the values have been
+ * written properly and read properly, we use the mState as an atomic synchronization
+ * point.  So if getState() shows READY, then all the other getters may
+ * be safely read.
+ *
+ * Technical details:
+ * We access the mState atomic value through memory_order_seq_cst
+ *
+ * https://en.cppreference.com/w/cpp/atomic/memory_order
+ *
+ * which provides memory barriers.  So if the last value written by the SoundDecoder
+ * is mState, then the compiler ensures no other prior writes by SoundDecoder will be
+ * reordered afterwards, and memory barrier is placed (as necessary) to ensure the
+ * cache is visible to other processors.
+ *
+ * Likewise, if the first value read by SoundPool is mState,
+ * the compiler ensures no reads for that thread will be reordered before mState is read,
+ * and a memory barrier is placed (as necessary) to ensure that the cache is properly
+ * updated with other processor's writes before reading.
+ *
+ * See https://developer.android.com/training/articles/smp for discussions about
+ * the variant load-acquire, store-release semantics.
+ */
+class Sound {
+    friend SoundDecoder;  // calls doLoad().
+
+public:
+    enum sound_state : int32_t { LOADING, READY, DECODE_ERROR };
+    // A sound starts in the LOADING state and transitions only once
+    // to either READY or DECODE_ERROR when doLoad() is called.
+
+    Sound(int soundID, int fd, int64_t offset, int64_t length);
+    ~Sound();
+
+    int32_t getSoundID() const { return mSoundID; }
+    int32_t getChannelCount() const { return mChannelCount; }
+    uint32_t getSampleRate() const { return mSampleRate; }
+    audio_format_t getFormat() const { return mFormat; }
+    audio_channel_mask_t getChannelMask() const { return mChannelMask; }
+    size_t getSizeInBytes() const { return mSizeInBytes; }
+    sound_state getState() const { return mState; }
+    uint8_t* getData() const { return static_cast<uint8_t*>(mData->unsecurePointer()); }
+    sp<IMemory> getIMemory() const { return mData; }
+
+private:
+    status_t doLoad();  // only SoundDecoder accesses this.
+
+    size_t               mSizeInBytes = 0;
+    const int32_t        mSoundID;
+    uint32_t             mSampleRate = 0;
+    std::atomic<sound_state> mState = LOADING; // used as synchronization point
+    int32_t              mChannelCount = 0;
+    audio_format_t       mFormat = AUDIO_FORMAT_INVALID;
+    audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
+    base::unique_fd      mFd;     // initialized in constructor, reset to -1 after loading
+    const int64_t        mOffset; // int64_t to match java long, see off64_t
+    const int64_t        mLength; // int64_t to match java long, see off64_t
+    sp<IMemory>          mData;
+    sp<MemoryHeapBase>   mHeap;
+};
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/SoundDecoder.cpp b/media/jni/soundpool/SoundDecoder.cpp
new file mode 100644
index 0000000..12200ef
--- /dev/null
+++ b/media/jni/soundpool/SoundDecoder.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool::SoundDecoder"
+#include "utils/Log.h"
+
+#include "SoundDecoder.h"
+
+namespace android::soundpool {
+
+// Maximum Samples that can be background decoded before we block the caller.
+static constexpr size_t kMaxQueueSize = 128;
+
+// The amount of time we wait for a new Sound decode request
+// before the SoundDecoder thread closes.
+static constexpr int32_t kWaitTimeBeforeCloseMs = 1000;
+
+SoundDecoder::SoundDecoder(SoundManager* soundManager, size_t threads)
+    : mSoundManager(soundManager)
+{
+    ALOGV("%s(%p, %zu)", __func__, soundManager, threads);
+    // ThreadPool is created, but we don't launch any threads.
+    mThreadPool = std::make_unique<ThreadPool>(
+            std::min(threads, (size_t)std::thread::hardware_concurrency()),
+            "SoundDecoder_");
+}
+
+SoundDecoder::~SoundDecoder()
+{
+    ALOGV("%s()", __func__);
+    quit();
+}
+
+void SoundDecoder::quit()
+{
+    ALOGV("%s()", __func__);
+    {
+        std::lock_guard lock(mLock);
+        mQuit = true;
+        mQueueSpaceAvailable.notify_all(); // notify all load waiters
+        mQueueDataAvailable.notify_all();  // notify all worker threads
+    }
+    mThreadPool->quit();
+}
+
+void SoundDecoder::run(int32_t id __unused /* ALOGV only */)
+{
+    ALOGV("%s(%d): entering", __func__, id);
+    std::unique_lock lock(mLock);
+    while (!mQuit) {
+        if (mSoundIDs.size() == 0) {
+            ALOGV("%s(%d): waiting", __func__, id);
+            mQueueDataAvailable.wait_for(
+                    lock, std::chrono::duration<int32_t, std::milli>(kWaitTimeBeforeCloseMs));
+            if (mSoundIDs.size() == 0) {
+                break; // no new sound, exit this thread.
+            }
+            continue;
+        }
+        const int32_t soundID = mSoundIDs.front();
+        mSoundIDs.pop_front();
+        mQueueSpaceAvailable.notify_one();
+        ALOGV("%s(%d): processing soundID: %d  size: %zu", __func__, id, soundID, mSoundIDs.size());
+        lock.unlock();
+        std::shared_ptr<Sound> sound = mSoundManager->findSound(soundID);
+        status_t status = NO_INIT;
+        if (sound.get() != nullptr) {
+            status = sound->doLoad();
+        }
+        ALOGV("%s(%d): notifying loaded soundID:%d  status:%d", __func__, id, soundID, status);
+        mSoundManager->notify(SoundPoolEvent(SoundPoolEvent::SOUND_LOADED, soundID, status));
+        lock.lock();
+    }
+    ALOGV("%s(%d): exiting", __func__, id);
+}
+
+void SoundDecoder::loadSound(int32_t soundID)
+{
+    ALOGV("%s(%d)", __func__, soundID);
+    size_t pendingSounds;
+    {
+        std::unique_lock lock(mLock);
+        while (mSoundIDs.size() == kMaxQueueSize) {
+            if (mQuit) return;
+            ALOGV("%s: waiting soundID: %d size: %zu", __func__, soundID, mSoundIDs.size());
+            mQueueSpaceAvailable.wait(lock);
+        }
+        if (mQuit) return;
+        mSoundIDs.push_back(soundID);
+        mQueueDataAvailable.notify_one();
+        ALOGV("%s: adding soundID: %d  size: %zu", __func__, soundID, mSoundIDs.size());
+        pendingSounds = mSoundIDs.size();
+    }
+    // Launch threads as needed.  The "as needed" is weakly consistent as we release mLock.
+    if (pendingSounds > mThreadPool->getActiveThreadCount()) {
+        const int32_t id __unused = mThreadPool->launch([this](int32_t id) { run(id); });
+        ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id);
+    }
+}
+
+} // end namespace android::soundpool
diff --git a/media/jni/soundpool/SoundDecoder.h b/media/jni/soundpool/SoundDecoder.h
new file mode 100644
index 0000000..1288943
--- /dev/null
+++ b/media/jni/soundpool/SoundDecoder.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "SoundPool.h"
+
+#include <deque>
+#include <mutex>
+
+namespace android::soundpool {
+
+/**
+ * SoundDecoder handles background decoding tasks.
+ */
+class SoundDecoder {
+public:
+    SoundDecoder(SoundManager* soundManager, size_t threads);
+    ~SoundDecoder();
+    void loadSound(int32_t soundID);
+    void quit();
+
+private:
+    void run(int32_t id);                       // The decode thread function.
+
+    SoundManager* const     mSoundManager;      // set in constructor, has own lock
+    std::unique_ptr<ThreadPool> mThreadPool;    // set in constructor, has own lock
+
+    std::mutex              mLock;
+    std::condition_variable mQueueSpaceAvailable;
+    std::condition_variable mQueueDataAvailable;
+
+    std::deque<int32_t>     mSoundIDs;            // GUARDED_BY(mLock);
+    bool                    mQuit = false;        // GUARDED_BY(mLock);
+};
+
+} // end namespace android::soundpool
+
diff --git a/media/jni/soundpool/SoundManager.cpp b/media/jni/soundpool/SoundManager.cpp
new file mode 100644
index 0000000..3c625bf
--- /dev/null
+++ b/media/jni/soundpool/SoundManager.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool::SoundManager"
+#include <utils/Log.h>
+
+#include "SoundManager.h"
+
+#include <thread>
+
+#include "SoundDecoder.h"
+
+namespace android::soundpool {
+
+static const size_t kDecoderThreads = std::thread::hardware_concurrency() >= 4 ? 2 : 1;
+
+SoundManager::SoundManager()
+    : mDecoder{std::make_unique<SoundDecoder>(this, kDecoderThreads)}
+{
+    ALOGV("%s()", __func__);
+}
+
+SoundManager::~SoundManager()
+{
+    ALOGV("%s()", __func__);
+    mDecoder->quit();
+
+    std::lock_guard lock(mSoundManagerLock);
+    mSounds.clear();
+}
+
+int32_t SoundManager::load(int fd, int64_t offset, int64_t length, int32_t priority __unused)
+{
+    ALOGV("%s(fd=%d, offset=%lld, length=%lld, priority=%d)",
+            __func__, fd, (long long)offset, (long long)length, priority);
+    int32_t soundID;
+    {
+        std::lock_guard lock(mSoundManagerLock);
+        // mNextSoundID is always positive and does not "integer overflow"
+        do {
+            mNextSoundID = mNextSoundID == INT32_MAX ? 1 : mNextSoundID + 1;
+        } while (findSound_l(mNextSoundID) != nullptr);
+        soundID = mNextSoundID;
+        auto sound = std::make_shared<Sound>(soundID, fd, offset, length);
+        mSounds.emplace(soundID, sound);
+    }
+    // mDecoder->loadSound() must be called outside of mSoundManagerLock.
+    // mDecoder->loadSound() may block on mDecoder message queue space;
+    // the message queue emptying may block on SoundManager::findSound().
+    //
+    // It is theoretically possible that sound loads might decode out-of-order.
+    mDecoder->loadSound(soundID);
+    return soundID;
+}
+
+bool SoundManager::unload(int32_t soundID)
+{
+    ALOGV("%s(soundID=%d)", __func__, soundID);
+    std::lock_guard lock(mSoundManagerLock);
+    return mSounds.erase(soundID) > 0; // erase() returns number of sounds removed.
+}
+
+std::shared_ptr<Sound> SoundManager::findSound(int32_t soundID) const
+{
+    std::lock_guard lock(mSoundManagerLock);
+    return findSound_l(soundID);
+}
+
+std::shared_ptr<Sound> SoundManager::findSound_l(int32_t soundID) const
+{
+    auto it = mSounds.find(soundID);
+    return it != mSounds.end() ? it->second : nullptr;
+}
+
+void SoundManager::setCallback(SoundPool *soundPool, SoundPoolCallback* callback, void* user)
+{
+    mCallbackHandler.setCallback(soundPool, callback, user);
+}
+
+void SoundManager::notify(SoundPoolEvent event)
+{
+    mCallbackHandler.notify(event);
+}
+
+void* SoundManager::getUserData() const
+{
+    return mCallbackHandler.getUserData();
+}
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/SoundManager.h b/media/jni/soundpool/SoundManager.h
new file mode 100644
index 0000000..9201e78
--- /dev/null
+++ b/media/jni/soundpool/SoundManager.h
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Sound.h"
+
+#include <mutex>
+#include <unordered_map>
+
+namespace android {
+
+class SoundPool;
+
+// for queued events
+class SoundPoolEvent {
+public:
+    explicit SoundPoolEvent(int msg, int arg1 = 0, int arg2 = 0) :
+        mMsg(msg), mArg1(arg1), mArg2(arg2) {}
+    const int mMsg;   // MessageType
+    const int mArg1;  // soundID
+    const int mArg2;  // status
+    enum MessageType { INVALID, SOUND_LOADED };
+};
+
+// callback function prototype
+typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
+
+} // namespace android
+
+namespace android::soundpool {
+
+// This class manages Sounds for the SoundPool.
+class SoundManager {
+public:
+    SoundManager();
+    ~SoundManager();
+
+    // Matches corresponding SoundPool API functions
+    int32_t load(int fd, int64_t offset, int64_t length, int32_t priority);
+    bool unload(int32_t soundID);
+    void setCallback(SoundPool* soundPool, SoundPoolCallback* callback, void* user);
+    void* getUserData() const;
+
+    // SoundPool and SoundDecoder access
+    std::shared_ptr<Sound> findSound(int32_t soundID) const;
+
+    // from the SoundDecoder
+    void notify(SoundPoolEvent event);
+
+private:
+
+    // CallbackHandler is used to manage notifications back to the app when a sound
+    // has been loaded.  It uses a recursive lock to allow setting the callback
+    // during the callback.
+    class CallbackHandler {
+    public:
+        void setCallback(SoundPool *soundPool, SoundPoolCallback* callback, void* userData)
+        {
+            std::lock_guard<std::recursive_mutex> lock(mCallbackLock);
+            mSoundPool = soundPool;
+            mCallback = callback;
+            mUserData = userData;
+        }
+        void notify(SoundPoolEvent event) const
+        {
+            std::lock_guard<std::recursive_mutex> lock(mCallbackLock);
+            if (mCallback != nullptr) {
+                mCallback(event, mSoundPool, mUserData);
+                // Note: mCallback may call setCallback().
+                // so mCallback, mUserData may have changed.
+            }
+        }
+        void* getUserData() const
+        {
+            std::lock_guard<std::recursive_mutex> lock(mCallbackLock);
+            return mUserData;
+        }
+    private:
+        mutable std::recursive_mutex  mCallbackLock; // allow mCallback to setCallback().
+        SoundPool*          mSoundPool = nullptr; // GUARDED_BY(mCallbackLock)
+        SoundPoolCallback*  mCallback = nullptr;  // GUARDED_BY(mCallbackLock)
+        void*               mUserData = nullptr;  // GUARDED_BY(mCallbackLock)
+    };
+
+    std::shared_ptr<Sound> findSound_l(int32_t soundID) const;
+
+    // The following variables are initialized in constructor and can be accessed anytime.
+    CallbackHandler         mCallbackHandler;              // has its own lock
+    const std::unique_ptr<SoundDecoder> mDecoder;          // has its own lock
+
+    mutable std::mutex      mSoundManagerLock;
+    std::unordered_map<int, std::shared_ptr<Sound>> mSounds; // GUARDED_BY(mSoundManagerLock)
+    int32_t                 mNextSoundID = 0;    // GUARDED_BY(mSoundManagerLock)
+};
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 102bbf0..ac44843 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -16,1124 +16,230 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoundPool"
-
-#include <chrono>
-#include <inttypes.h>
-#include <thread>
 #include <utils/Log.h>
 
-#define USE_SHARED_MEM_BUFFER
+#include <algorithm>
+#include <thread>
 
-#include <media/AudioTrack.h>
 #include "SoundPool.h"
-#include "SoundPoolThread.h"
-#include <media/NdkMediaCodec.h>
-#include <media/NdkMediaExtractor.h>
-#include <media/NdkMediaFormat.h>
 
 namespace android
 {
 
-int kDefaultBufferCount = 4;
-uint32_t kMaxSampleRate = 48000;
-uint32_t kDefaultSampleRate = 44100;
-uint32_t kDefaultFrameCount = 1200;
-size_t kDefaultHeapSize = 1024 * 1024; // 1MB
+// kManagerThreads = 1 historically.
+// Not really necessary to have more than one, but it does speed things up by about
+// 25% having 2 threads instead of 1 when playing many sounds.  Having many threads
+// could starve other AudioFlinger clients with SoundPool activity. It may also cause
+// issues with app loading, e.g. Camera.
+static const size_t kStreamManagerThreads = std::thread::hardware_concurrency() >= 4 ? 2 : 1;
 
+// kUseApiLock = true prior to R.
+// Set to true to prevent multiple users access internal to the SoundPool API.
+// Set to false to make the SoundPool methods weakly consistent.  When set to false,
+// only AutoPause and AutoResume are locked, which are the only two methods that
+// require API level locking for consistency.
+static constexpr bool kUseApiLock = false;
 
-SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes)
+namespace {
+// Check input arguments to SoundPool - return "true" to reject request.
+
+bool checkVolume(float *leftVolume, float *rightVolume)
 {
-    ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s",
-            maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags);
-
-    // check limits
-    mMaxChannels = maxChannels;
-    if (mMaxChannels < 1) {
-        mMaxChannels = 1;
+    if (*leftVolume != std::clamp(*leftVolume, 0.f, 1.f) ||
+            *rightVolume != std::clamp(*rightVolume, 0.f, 1.f)) {
+        ALOGI("volume l=%f r=%f out of (0.f, 1.f) bounds, using 1.f", *leftVolume, *rightVolume);
+        // for backward compatibility use 1.f.
+        *leftVolume = *rightVolume = 1.f;
     }
-    else if (mMaxChannels > 32) {
-        mMaxChannels = 32;
+    return false;
+}
+
+bool checkRate(float *rate)
+{
+    if (*rate != std::clamp(*rate, 0.125f, 8.f)) {
+        ALOGI("rate %f out of (0.125f, 8.f) bounds, clamping", *rate);
+        // for backward compatibility just clamp
+        *rate = std::clamp(*rate, 0.125f, 8.f);
     }
-    ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
+    return false;
+}
 
-    mQuit = false;
-    mMuted = false;
-    mDecodeThread = 0;
-    memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
-    mAllocated = 0;
-    mNextSampleID = 0;
-    mNextChannelID = 0;
-
-    mCallback = 0;
-    mUserData = 0;
-
-    mChannelPool = new SoundChannel[mMaxChannels];
-    for (int i = 0; i < mMaxChannels; ++i) {
-        mChannelPool[i].init(this);
-        mChannels.push_back(&mChannelPool[i]);
+bool checkPriority(int32_t *priority)
+{
+    if (*priority < 0) {
+        ALOGI("negative priority %d, should be >= 0.", *priority);
+        // for backward compatibility, ignore.
     }
+    return false;
+}
 
-    // start decode thread
-    startThreads();
+bool checkLoop(int32_t *loop)
+{
+    if (*loop < -1) {
+        ALOGI("loop %d, should be >= -1", *loop);
+        *loop = -1;
+    }
+    return false;
+}
+
+} // namespace
+
+SoundPool::SoundPool(int32_t maxStreams, const audio_attributes_t* attributes)
+    : mStreamManager(maxStreams, kStreamManagerThreads, attributes)
+{
+    ALOGV("%s(maxStreams=%d, attr={ content_type=%d, usage=%d, flags=0x%x, tags=%s })",
+            __func__, maxStreams,
+            attributes->content_type, attributes->usage, attributes->flags, attributes->tags);
 }
 
 SoundPool::~SoundPool()
 {
-    ALOGV("SoundPool destructor");
-    mDecodeThread->quit();
-    quit();
-
-    Mutex::Autolock lock(&mLock);
-
-    mChannels.clear();
-    if (mChannelPool)
-        delete [] mChannelPool;
-    // clean up samples
-    ALOGV("clear samples");
-    mSamples.clear();
-
-    if (mDecodeThread)
-        delete mDecodeThread;
+    ALOGV("%s()", __func__);
 }
 
-void SoundPool::addToRestartList(SoundChannel* channel)
+int32_t SoundPool::load(int fd, int64_t offset, int64_t length, int32_t priority)
 {
-    Mutex::Autolock lock(&mRestartLock);
-    if (!mQuit) {
-        mRestart.push_back(channel);
-        mCondition.signal();
-    }
+    ALOGV("%s(fd=%d, offset=%lld, length=%lld, priority=%d)",
+            __func__, fd, (long long)offset, (long long)length, priority);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    return mSoundManager.load(fd, offset, length, priority);
 }
 
-void SoundPool::addToStopList(SoundChannel* channel)
+bool SoundPool::unload(int32_t soundID)
 {
-    Mutex::Autolock lock(&mRestartLock);
-    if (!mQuit) {
-        mStop.push_back(channel);
-        mCondition.signal();
-    }
+    ALOGV("%s(%d)", __func__, soundID);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    return mSoundManager.unload(soundID);
 }
 
-int SoundPool::beginThread(void* arg)
+int32_t SoundPool::play(int32_t soundID, float leftVolume, float rightVolume,
+        int32_t priority, int32_t loop, float rate)
 {
-    SoundPool* p = (SoundPool*)arg;
-    return p->run();
-}
+    ALOGV("%s(soundID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f)",
+            __func__, soundID, leftVolume, rightVolume, priority, loop, rate);
 
-int SoundPool::run()
-{
-    mRestartLock.lock();
-    while (!mQuit) {
-        mCondition.wait(mRestartLock);
-        ALOGV("awake");
-        if (mQuit) break;
+    // New for R: check arguments to ensure track can be created.
+    // If SoundPool defers the creation of the AudioTrack to the StreamManager thread,
+    // the failure to create may not be visible to the caller, so this precheck is needed.
+    if (checkVolume(&leftVolume, &rightVolume)
+            || checkPriority(&priority)
+            || checkLoop(&loop)
+            || checkRate(&rate)) return 0;
 
-        while (!mStop.empty()) {
-            SoundChannel* channel;
-            ALOGV("Getting channel from stop list");
-            List<SoundChannel* >::iterator iter = mStop.begin();
-            channel = *iter;
-            mStop.erase(iter);
-            mRestartLock.unlock();
-            if (channel != 0) {
-                Mutex::Autolock lock(&mLock);
-                channel->stop();
-            }
-            mRestartLock.lock();
-            if (mQuit) break;
-        }
-
-        while (!mRestart.empty()) {
-            SoundChannel* channel;
-            ALOGV("Getting channel from list");
-            List<SoundChannel*>::iterator iter = mRestart.begin();
-            channel = *iter;
-            mRestart.erase(iter);
-            mRestartLock.unlock();
-            if (channel != 0) {
-                Mutex::Autolock lock(&mLock);
-                channel->nextEvent();
-            }
-            mRestartLock.lock();
-            if (mQuit) break;
-        }
-    }
-
-    mStop.clear();
-    mRestart.clear();
-    mCondition.signal();
-    mRestartLock.unlock();
-    ALOGV("goodbye");
-    return 0;
-}
-
-void SoundPool::quit()
-{
-    mRestartLock.lock();
-    mQuit = true;
-    mCondition.signal();
-    mCondition.wait(mRestartLock);
-    ALOGV("return from quit");
-    mRestartLock.unlock();
-}
-
-bool SoundPool::startThreads()
-{
-    createThreadEtc(beginThread, this, "SoundPool");
-    if (mDecodeThread == NULL)
-        mDecodeThread = new SoundPoolThread(this);
-    return mDecodeThread != NULL;
-}
-
-sp<Sample> SoundPool::findSample(int sampleID)
-{
-    Mutex::Autolock lock(&mLock);
-    return findSample_l(sampleID);
-}
-
-sp<Sample> SoundPool::findSample_l(int sampleID)
-{
-    return mSamples.valueFor(sampleID);
-}
-
-SoundChannel* SoundPool::findChannel(int channelID)
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        if (mChannelPool[i].channelID() == channelID) {
-            return &mChannelPool[i];
-        }
-    }
-    return NULL;
-}
-
-SoundChannel* SoundPool::findNextChannel(int channelID)
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        if (mChannelPool[i].nextChannelID() == channelID) {
-            return &mChannelPool[i];
-        }
-    }
-    return NULL;
-}
-
-int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused)
-{
-    ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
-            fd, offset, length, priority);
-    int sampleID;
-    {
-        Mutex::Autolock lock(&mLock);
-        sampleID = ++mNextSampleID;
-        sp<Sample> sample = new Sample(sampleID, fd, offset, length);
-        mSamples.add(sampleID, sample);
-        sample->startLoad();
-    }
-    // mDecodeThread->loadSample() must be called outside of mLock.
-    // mDecodeThread->loadSample() may block on mDecodeThread message queue space;
-    // the message queue emptying may block on SoundPool::findSample().
-    //
-    // It theoretically possible that sample loads might decode out-of-order.
-    mDecodeThread->loadSample(sampleID);
-    return sampleID;
-}
-
-bool SoundPool::unload(int sampleID)
-{
-    ALOGV("unload: sampleID=%d", sampleID);
-    Mutex::Autolock lock(&mLock);
-    return mSamples.removeItem(sampleID) >= 0; // removeItem() returns index or BAD_VALUE
-}
-
-int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
-        int priority, int loop, float rate)
-{
-    ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
-            sampleID, leftVolume, rightVolume, priority, loop, rate);
-    SoundChannel* channel;
-    int channelID;
-
-    Mutex::Autolock lock(&mLock);
-
-    if (mQuit) {
-        return 0;
-    }
-    // is sample ready?
-    sp<Sample> sample(findSample_l(sampleID));
-    if ((sample == 0) || (sample->state() != Sample::READY)) {
-        ALOGW("  sample %d not READY", sampleID);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    const std::shared_ptr<soundpool::Sound> sound = mSoundManager.findSound(soundID);
+    if (sound == nullptr || sound->getState() != soundpool::Sound::READY) {
+        ALOGW("%s soundID %d not READY", __func__, soundID);
         return 0;
     }
 
-    dump();
-
-    // allocate a channel
-    channel = allocateChannel_l(priority, sampleID);
-
-    // no channel allocated - return 0
-    if (!channel) {
-        ALOGV("No channel allocated");
-        return 0;
-    }
-
-    channelID = ++mNextChannelID;
-
-    ALOGV("play channel %p state = %d", channel, channel->state());
-    channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
-    return channelID;
-}
-
-SoundChannel* SoundPool::allocateChannel_l(int priority, int sampleID)
-{
-    List<SoundChannel*>::iterator iter;
-    SoundChannel* channel = NULL;
-
-    // check if channel for given sampleID still available
-    if (!mChannels.empty()) {
-        for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
-            if (sampleID == (*iter)->getPrevSampleID() && (*iter)->state() == SoundChannel::IDLE) {
-                channel = *iter;
-                mChannels.erase(iter);
-                ALOGV("Allocated recycled channel for same sampleID");
-                break;
-            }
-        }
-    }
-
-    // allocate any channel
-    if (!channel && !mChannels.empty()) {
-        iter = mChannels.begin();
-        if (priority >= (*iter)->priority()) {
-            channel = *iter;
-            mChannels.erase(iter);
-            ALOGV("Allocated active channel");
-        }
-    }
-
-    // update priority and put it back in the list
-    if (channel) {
-        channel->setPriority(priority);
-        for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
-            if (priority < (*iter)->priority()) {
-                break;
-            }
-        }
-        mChannels.insert(iter, channel);
-    }
-    return channel;
-}
-
-// move a channel from its current position to the front of the list
-void SoundPool::moveToFront_l(SoundChannel* channel)
-{
-    for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
-        if (*iter == channel) {
-            mChannels.erase(iter);
-            mChannels.push_front(channel);
-            break;
-        }
-    }
-}
-
-void SoundPool::pause(int channelID)
-{
-    ALOGV("pause(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->pause();
-    }
+    const int32_t streamID = mStreamManager.queueForPlay(
+            sound, soundID, leftVolume, rightVolume, priority, loop, rate);
+    ALOGV("%s returned %d", __func__, streamID);
+    return streamID;
 }
 
 void SoundPool::autoPause()
 {
-    ALOGV("autoPause()");
-    Mutex::Autolock lock(&mLock);
-    for (int i = 0; i < mMaxChannels; ++i) {
-        SoundChannel* channel = &mChannelPool[i];
-        channel->autoPause();
-    }
-}
-
-void SoundPool::resume(int channelID)
-{
-    ALOGV("resume(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->resume();
-    }
-}
-
-void SoundPool::mute(bool muting)
-{
-    ALOGV("mute(%d)", muting);
-    Mutex::Autolock lock(&mLock);
-    mMuted = muting;
-    if (!mChannels.empty()) {
-            for (List<SoundChannel*>::iterator iter = mChannels.begin();
-                    iter != mChannels.end(); ++iter) {
-                (*iter)->mute(muting);
-            }
-        }
+    ALOGV("%s()", __func__);
+    auto apiLock = std::make_unique<std::lock_guard<std::mutex>>(mApiLock);
+    mStreamManager.forEach([](soundpool::Stream *stream) { stream->autoPause(); });
 }
 
 void SoundPool::autoResume()
 {
-    ALOGV("autoResume()");
-    Mutex::Autolock lock(&mLock);
-    for (int i = 0; i < mMaxChannels; ++i) {
-        SoundChannel* channel = &mChannelPool[i];
-        channel->autoResume();
+    ALOGV("%s()", __func__);
+    auto apiLock = std::make_unique<std::lock_guard<std::mutex>>(mApiLock);
+    mStreamManager.forEach([](soundpool::Stream *stream) { stream->autoResume(); });
+}
+
+void SoundPool::mute(bool muting)
+{
+    ALOGV("%s(%d)", __func__, muting);
+    auto apiLock = std::make_unique<std::lock_guard<std::mutex>>(mApiLock);
+    mStreamManager.forEach([=](soundpool::Stream *stream) { stream->mute(muting); });
+}
+
+void SoundPool::pause(int32_t streamID)
+{
+    ALOGV("%s(%d)", __func__, streamID);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    if (soundpool::Stream* stream = mStreamManager.findStream(streamID)) {
+        stream->pause(streamID);
     }
 }
 
-void SoundPool::stop(int channelID)
+void SoundPool::resume(int32_t streamID)
 {
-    ALOGV("stop(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->stop();
-    } else {
-        channel = findNextChannel(channelID);
-        if (channel)
-            channel->clearNextEvent();
+    ALOGV("%s(%d)", __func__, streamID);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    if (soundpool::Stream* stream = mStreamManager.findStream(streamID)) {
+        stream->resume(streamID);
     }
 }
 
-void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
+void SoundPool::stop(int32_t streamID)
 {
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setVolume(leftVolume, rightVolume);
+    ALOGV("%s(%d)", __func__, streamID);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    soundpool::Stream* stream = mStreamManager.findStream(streamID);
+    if (stream != nullptr && stream->requestStop(streamID)) {
+        mStreamManager.moveToRestartQueue(stream);
     }
 }
 
-void SoundPool::setPriority(int channelID, int priority)
+void SoundPool::setVolume(int32_t streamID, float leftVolume, float rightVolume)
 {
-    ALOGV("setPriority(%d, %d)", channelID, priority);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setPriority(priority);
+    ALOGV("%s(%d, %f %f)", __func__, streamID, leftVolume, rightVolume);
+    if (checkVolume(&leftVolume, &rightVolume)) return;
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    if (soundpool::Stream* stream = mStreamManager.findStream(streamID)) {
+        stream->setVolume(streamID, leftVolume, rightVolume);
     }
 }
 
-void SoundPool::setLoop(int channelID, int loop)
+void SoundPool::setPriority(int32_t streamID, int32_t priority)
 {
-    ALOGV("setLoop(%d, %d)", channelID, loop);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setLoop(loop);
+    ALOGV("%s(%d, %d)", __func__, streamID, priority);
+    if (checkPriority(&priority)) return;
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    if (soundpool::Stream* stream = mStreamManager.findStream(streamID)) {
+        stream->setPriority(streamID, priority);
     }
 }
 
-void SoundPool::setRate(int channelID, float rate)
+void SoundPool::setLoop(int32_t streamID, int32_t loop)
 {
-    ALOGV("setRate(%d, %f)", channelID, rate);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setRate(rate);
+    ALOGV("%s(%d, %d)", __func__, streamID, loop);
+    if (checkLoop(&loop)) return;
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    if (soundpool::Stream* stream = mStreamManager.findStream(streamID)) {
+        stream->setLoop(streamID, loop);
     }
 }
 
-// call with lock held
-void SoundPool::done_l(SoundChannel* channel)
+void SoundPool::setRate(int32_t streamID, float rate)
 {
-    ALOGV("done_l(%d)", channel->channelID());
-    // if "stolen", play next event
-    if (channel->nextChannelID() != 0) {
-        ALOGV("add to restart list");
-        addToRestartList(channel);
-    }
-
-    // return to idle state
-    else {
-        ALOGV("move to front");
-        moveToFront_l(channel);
+    ALOGV("%s(%d, %f)", __func__, streamID, rate);
+    if (checkRate(&rate)) return;
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    if (soundpool::Stream* stream = mStreamManager.findStream(streamID)) {
+        stream->setRate(streamID, rate);
     }
 }
 
 void SoundPool::setCallback(SoundPoolCallback* callback, void* user)
 {
-    Mutex::Autolock lock(&mCallbackLock);
-    mCallback = callback;
-    mUserData = user;
+    ALOGV("%s(%p, %p)", __func__, callback, user);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    mSoundManager.setCallback(this, callback, user);
 }
 
-void SoundPool::notify(SoundPoolEvent event)
+void* SoundPool::getUserData() const
 {
-    Mutex::Autolock lock(&mCallbackLock);
-    if (mCallback != NULL) {
-        mCallback(event, this, mUserData);
-    }
-}
-
-void SoundPool::dump()
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        mChannelPool[i].dump();
-    }
-}
-
-
-Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
-{
-    init();
-    mSampleID = sampleID;
-    mFd = dup(fd);
-    mOffset = offset;
-    mLength = length;
-    ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64,
-        mSampleID, mFd, mLength, mOffset);
-}
-
-void Sample::init()
-{
-    mSize = 0;
-    mRefCount = 0;
-    mSampleID = 0;
-    mState = UNLOADED;
-    mFd = -1;
-    mOffset = 0;
-    mLength = 0;
-}
-
-Sample::~Sample()
-{
-    ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
-    if (mFd > 0) {
-        ALOGV("close(%d)", mFd);
-        ::close(mFd);
-    }
-}
-
-static status_t decode(int fd, int64_t offset, int64_t length,
-        uint32_t *rate, int *numChannels, audio_format_t *audioFormat,
-        audio_channel_mask_t *channelMask, sp<MemoryHeapBase> heap,
-        size_t *memsize) {
-
-    ALOGV("fd %d, offset %" PRId64 ", size %" PRId64, fd, offset, length);
-    AMediaExtractor *ex = AMediaExtractor_new();
-    status_t err = AMediaExtractor_setDataSourceFd(ex, fd, offset, length);
-
-    if (err != AMEDIA_OK) {
-        AMediaExtractor_delete(ex);
-        return err;
-    }
-
-    *audioFormat = AUDIO_FORMAT_PCM_16_BIT;
-
-    size_t numTracks = AMediaExtractor_getTrackCount(ex);
-    for (size_t i = 0; i < numTracks; i++) {
-        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
-        const char *mime;
-        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
-            AMediaExtractor_delete(ex);
-            AMediaFormat_delete(format);
-            return UNKNOWN_ERROR;
-        }
-        if (strncmp(mime, "audio/", 6) == 0) {
-
-            AMediaCodec *codec = AMediaCodec_createDecoderByType(mime);
-            if (codec == NULL
-                    || AMediaCodec_configure(codec, format,
-                            NULL /* window */, NULL /* drm */, 0 /* flags */) != AMEDIA_OK
-                    || AMediaCodec_start(codec) != AMEDIA_OK
-                    || AMediaExtractor_selectTrack(ex, i) != AMEDIA_OK) {
-                AMediaExtractor_delete(ex);
-                AMediaCodec_delete(codec);
-                AMediaFormat_delete(format);
-                return UNKNOWN_ERROR;
-            }
-
-            bool sawInputEOS = false;
-            bool sawOutputEOS = false;
-            uint8_t* writePos = static_cast<uint8_t*>(heap->getBase());
-            size_t available = heap->getSize();
-            size_t written = 0;
-
-            AMediaFormat_delete(format);
-            format = AMediaCodec_getOutputFormat(codec);
-
-            while (!sawOutputEOS) {
-                if (!sawInputEOS) {
-                    ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000);
-                    ALOGV("input buffer %zd", bufidx);
-                    if (bufidx >= 0) {
-                        size_t bufsize;
-                        uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
-                        if (buf == nullptr) {
-                            ALOGE("AMediaCodec_getInputBuffer returned nullptr, short decode");
-                            break;
-                        }
-                        int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
-                        ALOGV("read %d", sampleSize);
-                        if (sampleSize < 0) {
-                            sampleSize = 0;
-                            sawInputEOS = true;
-                            ALOGV("EOS");
-                        }
-                        int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
-
-                        media_status_t mstatus = AMediaCodec_queueInputBuffer(codec, bufidx,
-                                0 /* offset */, sampleSize, presentationTimeUs,
-                                sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
-                        if (mstatus != AMEDIA_OK) {
-                            // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES }
-                            ALOGE("AMediaCodec_queueInputBuffer returned status %d, short decode",
-                                    (int)mstatus);
-                            break;
-                        }
-                        (void)AMediaExtractor_advance(ex);
-                    }
-                }
-
-                AMediaCodecBufferInfo info;
-                int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1);
-                ALOGV("dequeueoutput returned: %d", status);
-                if (status >= 0) {
-                    if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
-                        ALOGV("output EOS");
-                        sawOutputEOS = true;
-                    }
-                    ALOGV("got decoded buffer size %d", info.size);
-
-                    uint8_t *buf = AMediaCodec_getOutputBuffer(codec, status, NULL /* out_size */);
-                    if (buf == nullptr) {
-                        ALOGE("AMediaCodec_getOutputBuffer returned nullptr, short decode");
-                        break;
-                    }
-                    size_t dataSize = info.size;
-                    if (dataSize > available) {
-                        dataSize = available;
-                    }
-                    memcpy(writePos, buf + info.offset, dataSize);
-                    writePos += dataSize;
-                    written += dataSize;
-                    available -= dataSize;
-                    media_status_t mstatus = AMediaCodec_releaseOutputBuffer(
-                            codec, status, false /* render */);
-                    if (mstatus != AMEDIA_OK) {
-                        // AMEDIA_ERROR_UNKNOWN == { -ERANGE -EINVAL -EACCES }
-                        ALOGE("AMediaCodec_releaseOutputBuffer returned status %d, short decode",
-                                (int)mstatus);
-                        break;
-                    }
-                    if (available == 0) {
-                        // there might be more data, but there's no space for it
-                        sawOutputEOS = true;
-                    }
-                } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
-                    ALOGV("output buffers changed");
-                } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
-                    AMediaFormat_delete(format);
-                    format = AMediaCodec_getOutputFormat(codec);
-                    ALOGV("format changed to: %s", AMediaFormat_toString(format));
-                } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
-                    ALOGV("no output buffer right now");
-                } else if (status <= AMEDIA_ERROR_BASE) {
-                    ALOGE("decode error: %d", status);
-                    break;
-                } else {
-                    ALOGV("unexpected info code: %d", status);
-                }
-            }
-
-            (void)AMediaCodec_stop(codec);
-            (void)AMediaCodec_delete(codec);
-            (void)AMediaExtractor_delete(ex);
-            if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) rate) ||
-                    !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, numChannels)) {
-                (void)AMediaFormat_delete(format);
-                return UNKNOWN_ERROR;
-            }
-            if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_MASK,
-                    (int32_t*) channelMask)) {
-                *channelMask = AUDIO_CHANNEL_NONE;
-            }
-            (void)AMediaFormat_delete(format);
-            *memsize = written;
-            return OK;
-        }
-        (void)AMediaFormat_delete(format);
-    }
-    (void)AMediaExtractor_delete(ex);
-    return UNKNOWN_ERROR;
-}
-
-status_t Sample::doLoad()
-{
-    uint32_t sampleRate;
-    int numChannels;
-    audio_format_t format;
-    audio_channel_mask_t channelMask;
-    status_t status;
-    mHeap = new MemoryHeapBase(kDefaultHeapSize);
-
-    ALOGV("Start decode");
-    status = decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format,
-                    &channelMask, mHeap, &mSize);
-    ALOGV("close(%d)", mFd);
-    ::close(mFd);
-    mFd = -1;
-    if (status != NO_ERROR) {
-        ALOGE("Unable to load sample");
-        goto error;
-    }
-    ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d",
-          mHeap->getBase(), mSize, sampleRate, numChannels);
-
-    if (sampleRate > kMaxSampleRate) {
-       ALOGE("Sample rate (%u) out of range", sampleRate);
-       status = BAD_VALUE;
-       goto error;
-    }
-
-    if ((numChannels < 1) || (numChannels > FCC_8)) {
-        ALOGE("Sample channel count (%d) out of range", numChannels);
-        status = BAD_VALUE;
-        goto error;
-    }
-
-    mData = new MemoryBase(mHeap, 0, mSize);
-    mSampleRate = sampleRate;
-    mNumChannels = numChannels;
-    mFormat = format;
-    mChannelMask = channelMask;
-    mState = READY;
-    return NO_ERROR;
-
-error:
-    mHeap.clear();
-    return status;
-}
-
-
-void SoundChannel::init(SoundPool* soundPool)
-{
-    mSoundPool = soundPool;
-    mPrevSampleID = -1;
-}
-
-// call with sound pool lock held
-void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
-        float rightVolume, int priority, int loop, float rate)
-{
-    sp<AudioTrack> oldTrack;
-    sp<AudioTrack> newTrack;
-    status_t status = NO_ERROR;
-
-    { // scope for the lock
-        Mutex::Autolock lock(&mLock);
-
-        ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
-                " priority=%d, loop=%d, rate=%f",
-                this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
-                priority, loop, rate);
-
-        // if not idle, this voice is being stolen
-        if (mState != IDLE) {
-            ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
-            mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-            stop_l();
-            return;
-        }
-
-        // initialize track
-        size_t afFrameCount;
-        uint32_t afSampleRate;
-        audio_stream_type_t streamType =
-                AudioSystem::attributesToStreamType(*mSoundPool->attributes());
-        if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
-            afFrameCount = kDefaultFrameCount;
-        }
-        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
-            afSampleRate = kDefaultSampleRate;
-        }
-        int numChannels = sample->numChannels();
-        uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
-        size_t frameCount = 0;
-
-        if (loop) {
-            const audio_format_t format = sample->format();
-            const size_t frameSize = audio_is_linear_pcm(format)
-                    ? numChannels * audio_bytes_per_sample(format) : 1;
-            frameCount = sample->size() / frameSize;
-        }
-
-#ifndef USE_SHARED_MEM_BUFFER
-        uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
-        // Ensure minimum audio buffer size in case of short looped sample
-        if(frameCount < totalFrames) {
-            frameCount = totalFrames;
-        }
-#endif
-
-        // check if the existing track has the same sample id.
-        if (mAudioTrack != 0 && mPrevSampleID == sample->sampleID()) {
-            // the sample rate may fail to change if the audio track is a fast track.
-            if (mAudioTrack->setSampleRate(sampleRate) == NO_ERROR) {
-                newTrack = mAudioTrack;
-                ALOGV("reusing track %p for sample %d", mAudioTrack.get(), sample->sampleID());
-            }
-        }
-        if (newTrack == 0) {
-            // mToggle toggles each time a track is started on a given channel.
-            // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
-            // as callback user data. This enables the detection of callbacks received from the old
-            // audio track while the new one is being started and avoids processing them with
-            // wrong audio audio buffer size  (mAudioBufferSize)
-            unsigned long toggle = mToggle ^ 1;
-            void *userData = (void *)((unsigned long)this | toggle);
-            audio_channel_mask_t sampleChannelMask = sample->channelMask();
-            // When sample contains a not none channel mask, use it as is.
-            // Otherwise, use channel count to calculate channel mask.
-            audio_channel_mask_t channelMask = sampleChannelMask != AUDIO_CHANNEL_NONE
-                    ? sampleChannelMask : audio_channel_out_mask_from_count(numChannels);
-
-            // do not create a new audio track if current track is compatible with sample parameters
-    #ifdef USE_SHARED_MEM_BUFFER
-            newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-                    channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData,
-                    0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
-                    AudioTrack::TRANSFER_DEFAULT,
-                    NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes());
-    #else
-            uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
-            newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-                    channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
-                    bufferFrames, AUDIO_SESSION_ALLOCATE, AudioTrack::TRANSFER_DEFAULT,
-                    NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes());
-    #endif
-            oldTrack = mAudioTrack;
-            status = newTrack->initCheck();
-            if (status != NO_ERROR) {
-                ALOGE("Error creating AudioTrack");
-                // newTrack goes out of scope, so reference count drops to zero
-                goto exit;
-            }
-            // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
-            mToggle = toggle;
-            mAudioTrack = newTrack;
-            ALOGV("using new track %p for sample %d", newTrack.get(), sample->sampleID());
-        }
-        if (mMuted) {
-            newTrack->setVolume(0.0f, 0.0f);
-        } else {
-            newTrack->setVolume(leftVolume, rightVolume);
-        }
-        newTrack->setLoop(0, frameCount, loop);
-        mPos = 0;
-        mSample = sample;
-        mChannelID = nextChannelID;
-        mPriority = priority;
-        mLoop = loop;
-        mLeftVolume = leftVolume;
-        mRightVolume = rightVolume;
-        mNumChannels = numChannels;
-        mRate = rate;
-        clearNextEvent();
-        mState = PLAYING;
-        mAudioTrack->start();
-        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
-    }
-
-exit:
-    ALOGV("delete oldTrack %p", oldTrack.get());
-    if (status != NO_ERROR) {
-        mAudioTrack.clear();
-    }
-}
-
-void SoundChannel::nextEvent()
-{
-    sp<Sample> sample;
-    int nextChannelID;
-    float leftVolume;
-    float rightVolume;
-    int priority;
-    int loop;
-    float rate;
-
-    // check for valid event
-    {
-        Mutex::Autolock lock(&mLock);
-        nextChannelID = mNextEvent.channelID();
-        if (nextChannelID  == 0) {
-            ALOGV("stolen channel has no event");
-            return;
-        }
-
-        sample = mNextEvent.sample();
-        leftVolume = mNextEvent.leftVolume();
-        rightVolume = mNextEvent.rightVolume();
-        priority = mNextEvent.priority();
-        loop = mNextEvent.loop();
-        rate = mNextEvent.rate();
-    }
-
-    ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
-    play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-}
-
-void SoundChannel::callback(int event, void* user, void *info)
-{
-    SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
-
-    channel->process(event, info, (unsigned long)user & 1);
-}
-
-void SoundChannel::process(int event, void *info, unsigned long toggle)
-{
-    //ALOGV("process(%d)", mChannelID);
-
-    Mutex::Autolock lock(&mLock);
-
-    AudioTrack::Buffer* b = NULL;
-    if (event == AudioTrack::EVENT_MORE_DATA) {
-       b = static_cast<AudioTrack::Buffer *>(info);
-    }
-
-    if (mToggle != toggle) {
-        ALOGV("process wrong toggle %p channel %d", this, mChannelID);
-        if (b != NULL) {
-            b->size = 0;
-        }
-        return;
-    }
-
-    sp<Sample> sample = mSample;
-
-//    ALOGV("SoundChannel::process event %d", event);
-
-    if (event == AudioTrack::EVENT_MORE_DATA) {
-
-        // check for stop state
-        if (b->size == 0) return;
-
-        if (mState == IDLE) {
-            b->size = 0;
-            return;
-        }
-
-        if (sample != 0) {
-            // fill buffer
-            uint8_t* q = (uint8_t*) b->i8;
-            size_t count = 0;
-
-            if (mPos < (int)sample->size()) {
-                uint8_t* p = sample->data() + mPos;
-                count = sample->size() - mPos;
-                if (count > b->size) {
-                    count = b->size;
-                }
-                memcpy(q, p, count);
-//              ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size,
-//                      count);
-            } else if (mPos < mAudioBufferSize) {
-                count = mAudioBufferSize - mPos;
-                if (count > b->size) {
-                    count = b->size;
-                }
-                memset(q, 0, count);
-//              ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
-            }
-
-            mPos += count;
-            b->size = count;
-            //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
-        }
-    } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) {
-        ALOGV("process %p channel %d event %s",
-              this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" :
-                      "BUFFER_END");
-        // Only BUFFER_END should happen as we use static tracks.
-        setVolume_l(0.f, 0.f);  // set volume to 0 to indicate no need to ramp volume down.
-        mSoundPool->addToStopList(this);
-    } else if (event == AudioTrack::EVENT_LOOP_END) {
-        ALOGV("End loop %p channel %d", this, mChannelID);
-    } else if (event == AudioTrack::EVENT_NEW_IAUDIOTRACK) {
-        ALOGV("process %p channel %d NEW_IAUDIOTRACK", this, mChannelID);
-    } else {
-        ALOGW("SoundChannel::process unexpected event %d", event);
-    }
-}
-
-
-// call with lock held
-bool SoundChannel::doStop_l()
-{
-    if (mState != IDLE) {
-        ALOGV("stop");
-        if (mLeftVolume != 0.f || mRightVolume != 0.f) {
-            setVolume_l(0.f, 0.f);
-            if (mSoundPool->attributes()->usage != AUDIO_USAGE_GAME) {
-                // Since we're forcibly halting the previously playing content,
-                // we sleep here to ensure the volume is ramped down before we stop the track.
-                // Ideally the sleep time is the mixer period, or an approximation thereof
-                // (Fast vs Normal tracks are different).
-                ALOGV("sleeping: ChannelID:%d  SampleID:%d", mChannelID, mSample->sampleID());
-                std::this_thread::sleep_for(std::chrono::milliseconds(20));
-            }
-        }
-        mAudioTrack->stop();
-        mPrevSampleID = mSample->sampleID();
-        mSample.clear();
-        mState = IDLE;
-        mPriority = IDLE_PRIORITY;
-        return true;
-    }
-    return false;
-}
-
-// call with lock held and sound pool lock held
-void SoundChannel::stop_l()
-{
-    if (doStop_l()) {
-        mSoundPool->done_l(this);
-    }
-}
-
-// call with sound pool lock held
-void SoundChannel::stop()
-{
-    bool stopped;
-    {
-        Mutex::Autolock lock(&mLock);
-        stopped = doStop_l();
-    }
-
-    if (stopped) {
-        mSoundPool->done_l(this);
-    }
-}
-
-//FIXME: Pause is a little broken right now
-void SoundChannel::pause()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PLAYING) {
-        ALOGV("pause track");
-        mState = PAUSED;
-        mAudioTrack->pause();
-    }
-}
-
-void SoundChannel::autoPause()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PLAYING) {
-        ALOGV("pause track");
-        mState = PAUSED;
-        mAutoPaused = true;
-        mAudioTrack->pause();
-    }
-}
-
-void SoundChannel::resume()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PAUSED) {
-        ALOGV("resume track");
-        mState = PLAYING;
-        mAutoPaused = false;
-        mAudioTrack->start();
-    }
-}
-
-void SoundChannel::autoResume()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAutoPaused && (mState == PAUSED)) {
-        ALOGV("resume track");
-        mState = PLAYING;
-        mAutoPaused = false;
-        mAudioTrack->start();
-    }
-}
-
-void SoundChannel::setRate(float rate)
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAudioTrack != NULL && mSample != 0) {
-        uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
-        mAudioTrack->setSampleRate(sampleRate);
-        mRate = rate;
-    }
-}
-
-// call with lock held
-void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
-{
-    mLeftVolume = leftVolume;
-    mRightVolume = rightVolume;
-    if (mAudioTrack != NULL && !mMuted)
-        mAudioTrack->setVolume(leftVolume, rightVolume);
-}
-
-void SoundChannel::setVolume(float leftVolume, float rightVolume)
-{
-    Mutex::Autolock lock(&mLock);
-    setVolume_l(leftVolume, rightVolume);
-}
-
-void SoundChannel::mute(bool muting)
-{
-    Mutex::Autolock lock(&mLock);
-    mMuted = muting;
-    if (mAudioTrack != NULL) {
-        if (mMuted) {
-            mAudioTrack->setVolume(0.0f, 0.0f);
-        } else {
-            mAudioTrack->setVolume(mLeftVolume, mRightVolume);
-        }
-    }
-}
-
-void SoundChannel::setLoop(int loop)
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAudioTrack != NULL && mSample != 0) {
-        uint32_t loopEnd = mSample->size()/mNumChannels/
-            ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
-        mAudioTrack->setLoop(0, loopEnd, loop);
-        mLoop = loop;
-    }
-}
-
-SoundChannel::~SoundChannel()
-{
-    ALOGV("SoundChannel destructor %p", this);
-    {
-        Mutex::Autolock lock(&mLock);
-        clearNextEvent();
-        doStop_l();
-    }
-    // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
-    // callback thread to exit which may need to execute process() and acquire the mLock.
-    mAudioTrack.clear();
-}
-
-void SoundChannel::dump()
-{
-    ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
-            mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
-}
-
-void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
-            float rightVolume, int priority, int loop, float rate)
-{
-    mSample = sample;
-    mChannelID = channelID;
-    mLeftVolume = leftVolume;
-    mRightVolume = rightVolume;
-    mPriority = priority;
-    mLoop = loop;
-    mRate =rate;
+    ALOGV("%s()", __func__);
+    auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr;
+    return mSoundManager.getUserData();
 }
 
 } // end namespace android
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 01e4faa..d5b16ef 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -14,227 +14,59 @@
  * limitations under the License.
  */
 
-#ifndef SOUNDPOOL_H_
-#define SOUNDPOOL_H_
+#pragma once
 
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-#include <media/AudioTrack.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/MemoryBase.h>
+#include "SoundManager.h"
+#include "StreamManager.h"
 
 namespace android {
 
-static const int IDLE_PRIORITY = -1;
-
-// forward declarations
-class SoundEvent;
-class SoundPoolThread;
-class SoundPool;
-
-// for queued events
-class SoundPoolEvent {
-public:
-    explicit SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
-        mMsg(msg), mArg1(arg1), mArg2(arg2) {}
-    int         mMsg;
-    int         mArg1;
-    int         mArg2;
-    enum MessageType { INVALID, SAMPLE_LOADED };
-};
-
-// callback function prototype
-typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
-
-// tracks samples used by application
-class Sample  : public RefBase {
-public:
-    enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
-    Sample(int sampleID, int fd, int64_t offset, int64_t length);
-    ~Sample();
-    int sampleID() { return mSampleID; }
-    int numChannels() { return mNumChannels; }
-    int sampleRate() { return mSampleRate; }
-    audio_format_t format() { return mFormat; }
-    audio_channel_mask_t channelMask() { return mChannelMask; }
-    size_t size() { return mSize; }
-    int state() { return mState; }
-    uint8_t* data() { return static_cast<uint8_t*>(mData->unsecurePointer()); }
-    status_t doLoad();
-    void startLoad() { mState = LOADING; }
-    sp<IMemory> getIMemory() { return mData; }
-
-private:
-    void init();
-
-    size_t               mSize;
-    volatile int32_t     mRefCount;
-    uint16_t             mSampleID;
-    uint16_t             mSampleRate;
-    uint8_t              mState;
-    uint8_t              mNumChannels;
-    audio_format_t       mFormat;
-    audio_channel_mask_t mChannelMask;
-    int                  mFd;
-    int64_t              mOffset;
-    int64_t              mLength;
-    sp<IMemory>          mData;
-    sp<MemoryHeapBase>   mHeap;
-};
-
-// stores pending events for stolen channels
-class SoundEvent
-{
-public:
-    SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
-            mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
-    void set(const sp<Sample>& sample, int channelID, float leftVolume,
-            float rightVolume, int priority, int loop, float rate);
-    sp<Sample>      sample() { return mSample; }
-    int             channelID() { return mChannelID; }
-    float           leftVolume() { return mLeftVolume; }
-    float           rightVolume() { return mRightVolume; }
-    int             priority() { return mPriority; }
-    int             loop() { return mLoop; }
-    float           rate() { return mRate; }
-    void            clear() { mChannelID = 0; mSample.clear(); }
-
-protected:
-    sp<Sample>      mSample;
-    int             mChannelID;
-    float           mLeftVolume;
-    float           mRightVolume;
-    int             mPriority;
-    int             mLoop;
-    float           mRate;
-};
-
-// for channels aka AudioTracks
-class SoundChannel : public SoundEvent {
-public:
-    enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
-    SoundChannel() : mState(IDLE), mNumChannels(1),
-            mPos(0), mToggle(0), mAutoPaused(false), mMuted(false) {}
-    ~SoundChannel();
-    void init(SoundPool* soundPool);
-    void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
-            int priority, int loop, float rate);
-    void setVolume_l(float leftVolume, float rightVolume);
-    void setVolume(float leftVolume, float rightVolume);
-    void mute(bool muting);
-    void stop_l();
-    void stop();
-    void pause();
-    void autoPause();
-    void resume();
-    void autoResume();
-    void setRate(float rate);
-    int state() { return mState; }
-    void setPriority(int priority) { mPriority = priority; }
-    void setLoop(int loop);
-    int numChannels() { return mNumChannels; }
-    void clearNextEvent() { mNextEvent.clear(); }
-    void nextEvent();
-    int nextChannelID() { return mNextEvent.channelID(); }
-    void dump();
-    int getPrevSampleID(void) { return mPrevSampleID; }
-
-private:
-    static void callback(int event, void* user, void *info);
-    void process(int event, void *info, unsigned long toggle);
-    bool doStop_l();
-
-    SoundPool*          mSoundPool;
-    sp<AudioTrack>      mAudioTrack;
-    SoundEvent          mNextEvent;
-    Mutex               mLock;
-    int                 mState;
-    int                 mNumChannels;
-    int                 mPos;
-    int                 mAudioBufferSize;
-    unsigned long       mToggle;
-    bool                mAutoPaused;
-    int                 mPrevSampleID;
-    bool                mMuted;
-};
-
-// application object for managing a pool of sounds
+/**
+ * Native class for Java SoundPool, manages a pool of sounds.
+ *
+ * See the Android SoundPool Java documentation for description of valid values.
+ * https://developer.android.com/reference/android/media/SoundPool
+ */
 class SoundPool {
-    friend class SoundPoolThread;
-    friend class SoundChannel;
 public:
-    SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
+    SoundPool(int32_t maxStreams, const audio_attributes_t* attributes);
     ~SoundPool();
-    int load(int fd, int64_t offset, int64_t length, int priority);
-    bool unload(int sampleID);
-    int play(int sampleID, float leftVolume, float rightVolume, int priority,
-            int loop, float rate);
-    void pause(int channelID);
-    void mute(bool muting);
+
+    // SoundPool Java API support
+    int32_t load(int fd, int64_t offset, int64_t length, int32_t priority);
+    bool unload(int32_t soundID);
+    int32_t play(int32_t soundID, float leftVolume, float rightVolume, int32_t priority,
+            int32_t loop, float rate);
+    void pause(int32_t streamID);
     void autoPause();
-    void resume(int channelID);
+    void resume(int32_t streamID);
     void autoResume();
-    void stop(int channelID);
-    void setVolume(int channelID, float leftVolume, float rightVolume);
-    void setPriority(int channelID, int priority);
-    void setLoop(int channelID, int loop);
-    void setRate(int channelID, float rate);
-    const audio_attributes_t* attributes() { return &mAttributes; }
-
-    // called from SoundPoolThread
-    void sampleLoaded(int sampleID);
-    sp<Sample> findSample(int sampleID);
-
-    // called from AudioTrack thread
-    void done_l(SoundChannel* channel);
-
-    // callback function
+    void stop(int32_t streamID);
+    void setVolume(int32_t streamID, float leftVolume, float rightVolume);
+    void setPriority(int32_t streamID, int32_t priority);
+    void setLoop(int32_t streamID, int32_t loop);
+    void setRate(int32_t streamID, float rate);
     void setCallback(SoundPoolCallback* callback, void* user);
-    void* getUserData() { return mUserData; }
+    void* getUserData() const;
+
+    // not exposed in the public Java API, used for internal playerSetVolume() muting.
+    void mute(bool muting);
 
 private:
-    SoundPool() {} // no default constructor
-    bool startThreads();
-    sp<Sample> findSample_l(int sampleID);
-    SoundChannel* findChannel (int channelID);
-    SoundChannel* findNextChannel (int channelID);
-    SoundChannel* allocateChannel_l(int priority, int sampleID);
-    void moveToFront_l(SoundChannel* channel);
-    void notify(SoundPoolEvent event);
-    void dump();
 
-    // restart thread
-    void addToRestartList(SoundChannel* channel);
-    void addToStopList(SoundChannel* channel);
-    static int beginThread(void* arg);
-    int run();
-    void quit();
+    // Constructor initialized variables
+    // Can access without lock as they are internally locked,
+    // though care needs to be taken that the final result composed of
+    // individually consistent actions are consistent.
+    soundpool::SoundManager  mSoundManager;
+    soundpool::StreamManager mStreamManager;
 
-    Mutex                   mLock;
-    Mutex                   mRestartLock;
-    Condition               mCondition;
-    SoundPoolThread*        mDecodeThread;
-    SoundChannel*           mChannelPool;
-    List<SoundChannel*>     mChannels;
-    List<SoundChannel*>     mRestart;
-    List<SoundChannel*>     mStop;
-    DefaultKeyedVector< int, sp<Sample> >   mSamples;
-    int                     mMaxChannels;
-    audio_attributes_t      mAttributes;
-    int                     mAllocated;
-    int                     mNextSampleID;
-    int                     mNextChannelID;
-    bool                    mQuit;
-    bool                    mMuted;
-
-    // callback
-    Mutex                   mCallbackLock;
-    SoundPoolCallback*      mCallback;
-    void*                   mUserData;
+    // mApiLock serializes SoundPool application calls (configurable by kUseApiLock).
+    // It only locks at the SoundPool layer and not below.  At this level,
+    // mApiLock is only required for autoPause() and autoResume() to prevent zippering
+    // of the individual pauses and resumes, and mute() for self-interaction with itself.
+    // It is optional for all other apis.
+    mutable std::mutex        mApiLock;
 };
 
 } // end namespace android
-
-#endif /*SOUNDPOOL_H_*/
diff --git a/media/jni/soundpool/SoundPoolThread.cpp b/media/jni/soundpool/SoundPoolThread.cpp
deleted file mode 100644
index ba3b482..0000000
--- a/media/jni/soundpool/SoundPoolThread.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "SoundPoolThread"
-#include "utils/Log.h"
-
-#include "SoundPoolThread.h"
-
-namespace android {
-
-void SoundPoolThread::write(SoundPoolMsg msg) {
-    Mutex::Autolock lock(&mLock);
-    while (mMsgQueue.size() >= maxMessages) {
-        mCondition.wait(mLock);
-    }
-
-    // if thread is quitting, don't add to queue
-    if (mRunning) {
-        mMsgQueue.push(msg);
-        mCondition.signal();
-    }
-}
-
-const SoundPoolMsg SoundPoolThread::read() {
-    Mutex::Autolock lock(&mLock);
-    while (mMsgQueue.size() == 0) {
-        mCondition.wait(mLock);
-    }
-    SoundPoolMsg msg = mMsgQueue[0];
-    mMsgQueue.removeAt(0);
-    mCondition.signal();
-    return msg;
-}
-
-void SoundPoolThread::quit() {
-    Mutex::Autolock lock(&mLock);
-    if (mRunning) {
-        mRunning = false;
-        mMsgQueue.clear();
-        mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
-        mCondition.signal();
-        mCondition.wait(mLock);
-    }
-    ALOGV("return from quit");
-}
-
-SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
-    mSoundPool(soundPool)
-{
-    mMsgQueue.setCapacity(maxMessages);
-    if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
-        mRunning = true;
-    }
-}
-
-SoundPoolThread::~SoundPoolThread()
-{
-    quit();
-}
-
-int SoundPoolThread::beginThread(void* arg) {
-    ALOGV("beginThread");
-    SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
-    return soundPoolThread->run();
-}
-
-int SoundPoolThread::run() {
-    ALOGV("run");
-    for (;;) {
-        SoundPoolMsg msg = read();
-        ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
-        switch (msg.mMessageType) {
-        case SoundPoolMsg::KILL:
-            ALOGV("goodbye");
-            return NO_ERROR;
-        case SoundPoolMsg::LOAD_SAMPLE:
-            doLoadSample(msg.mData);
-            break;
-        default:
-            ALOGW("run: Unrecognized message %d\n",
-                    msg.mMessageType);
-            break;
-        }
-    }
-}
-
-void SoundPoolThread::loadSample(int sampleID) {
-    write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
-}
-
-void SoundPoolThread::doLoadSample(int sampleID) {
-    sp <Sample> sample = mSoundPool->findSample(sampleID);
-    status_t status = -1;
-    if (sample != 0) {
-        status = sample->doLoad();
-    }
-    mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
-}
-
-} // end namespace android
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
deleted file mode 100644
index 7b3e1dd..0000000
--- a/media/jni/soundpool/SoundPoolThread.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#ifndef SOUNDPOOLTHREAD_H_
-#define SOUNDPOOLTHREAD_H_
-
-#include <utils/threads.h>
-#include <utils/Vector.h>
-#include <media/AudioTrack.h>
-
-#include "SoundPool.h"
-
-namespace android {
-
-class SoundPoolMsg {
-public:
-    enum MessageType { INVALID, KILL, LOAD_SAMPLE };
-    SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
-    SoundPoolMsg(MessageType MessageType, int data) :
-        mMessageType(MessageType), mData(data) {}
-    uint16_t         mMessageType;
-    uint16_t         mData;
-};
-
-/*
- * This class handles background requests from the SoundPool
- */
-class SoundPoolThread {
-public:
-    explicit SoundPoolThread(SoundPool* SoundPool);
-    ~SoundPoolThread();
-    void loadSample(int sampleID);
-    void quit();
-    void write(SoundPoolMsg msg);
-
-private:
-    static const size_t maxMessages = 128;
-
-    static int beginThread(void* arg);
-    int run();
-    void doLoadSample(int sampleID);
-    const SoundPoolMsg read();
-
-    Mutex                   mLock;
-    Condition               mCondition;
-    Vector<SoundPoolMsg>    mMsgQueue;
-    SoundPool*              mSoundPool;
-    bool                    mRunning;
-};
-
-} // end namespace android
-
-#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
new file mode 100644
index 0000000..e7d4d90
--- /dev/null
+++ b/media/jni/soundpool/Stream.cpp
@@ -0,0 +1,448 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool::Stream"
+#include <utils/Log.h>
+
+#include "Stream.h"
+
+#include "StreamManager.h"
+
+namespace android::soundpool {
+
+Stream::~Stream()
+{
+    ALOGV("%s(%p)", __func__, this);
+}
+
+void Stream::autoPause()
+{
+    std::lock_guard lock(mLock);
+    if (mState == PLAYING) {
+        ALOGV("%s: track streamID: %d", __func__, (int)mStreamID);
+        mState = PAUSED;
+        mAutoPaused = true;
+        if (mAudioTrack != nullptr) {
+            mAudioTrack->pause();
+        }
+    }
+}
+
+void Stream::autoResume()
+{
+    std::lock_guard lock(mLock);
+    if (mAutoPaused) {
+        if (mState == PAUSED) {
+            ALOGV("%s: track streamID: %d", __func__, (int)mStreamID);
+            mState = PLAYING;
+            if (mAudioTrack != nullptr) {
+                mAudioTrack->start();
+            }
+        }
+        mAutoPaused = false; // New for R: always reset autopause (consistent with API spec).
+    }
+}
+
+void Stream::mute(bool muting)
+{
+    std::lock_guard lock(mLock);
+    mMuted = muting;
+    if (mAudioTrack != nullptr) {
+        if (mMuted) {
+            mAudioTrack->setVolume(0.0f, 0.0f);
+        } else {
+            mAudioTrack->setVolume(mLeftVolume, mRightVolume);
+        }
+    }
+}
+
+void Stream::pause(int32_t streamID)
+{
+    std::lock_guard lock(mLock);
+    if (streamID == mStreamID) {
+        if (mState == PLAYING) {
+            ALOGV("%s: track streamID: %d", __func__, streamID);
+            mState = PAUSED;
+            if (mAudioTrack != nullptr) {
+                mAudioTrack->pause();
+            }
+        }
+    }
+}
+
+void Stream::resume(int32_t streamID)
+{
+    std::lock_guard lock(mLock);
+    if (streamID == mStreamID) {
+         if (mState == PAUSED) {
+            ALOGV("%s: track streamID: %d", __func__, streamID);
+            mState = PLAYING;
+            if (mAudioTrack != nullptr) {
+                mAudioTrack->start();
+            }
+            mAutoPaused = false; // TODO: is this right? (ambiguous per spec), move outside?
+        }
+    }
+}
+
+void Stream::setRate(int32_t streamID, float rate)
+{
+    std::lock_guard lock(mLock);
+    if (streamID == mStreamID) {
+        mRate = rate;
+        if (mAudioTrack != nullptr && mSound != nullptr) {
+            const uint32_t sampleRate = uint32_t(float(mSound->getSampleRate()) * rate + 0.5);
+            mAudioTrack->setSampleRate(sampleRate);
+        }
+    }
+}
+
+void Stream::setVolume_l(float leftVolume, float rightVolume)
+{
+    mLeftVolume = leftVolume;
+    mRightVolume = rightVolume;
+    if (mAudioTrack != nullptr && !mMuted) {
+        mAudioTrack->setVolume(leftVolume, rightVolume);
+    }
+}
+
+void Stream::setVolume(int32_t streamID, float leftVolume, float rightVolume)
+{
+    std::lock_guard lock(mLock);
+    if (streamID == mStreamID) {
+        setVolume_l(leftVolume, rightVolume);
+    }
+}
+
+void Stream::setPriority(int32_t streamID, int32_t priority)
+{
+    std::lock_guard lock(mLock);
+    if (streamID == mStreamID) {
+        mPriority = priority;
+    }
+}
+
+void Stream::setLoop(int32_t streamID, int32_t loop)
+{
+    std::lock_guard lock(mLock);
+    if (streamID == mStreamID) {
+        if (mAudioTrack != nullptr && mSound != nullptr) {
+            const uint32_t loopEnd = mSound->getSizeInBytes() / mSound->getChannelCount() /
+                (mSound->getFormat() == AUDIO_FORMAT_PCM_16_BIT
+                        ? sizeof(int16_t) : sizeof(uint8_t));
+            mAudioTrack->setLoop(0, loopEnd, loop);
+        }
+        mLoop = loop;
+    }
+}
+
+void Stream::setPlay(
+        int32_t streamID, const std::shared_ptr<Sound> &sound, int32_t soundID,
+        float leftVolume, float rightVolume, int32_t priority, int32_t loop, float rate)
+{
+    std::lock_guard lock(mLock);
+    // We must be idle, or we must be repurposing a pending Stream.
+    LOG_ALWAYS_FATAL_IF(mState != IDLE && mAudioTrack != nullptr, "State %d must be IDLE", mState);
+    mSound = sound;
+    mSoundID = soundID;
+    mLeftVolume = leftVolume;
+    mRightVolume = rightVolume;
+    mPriority = priority;
+    mLoop = loop;
+    mRate = rate;
+    mState = PLAYING;
+    mAutoPaused = false;   // New for R (consistent with Java API spec).
+    mStreamID = streamID;  // prefer this to be the last, as it is an atomic sync point
+}
+
+void Stream::setStopTimeNs(int64_t stopTimeNs)
+{
+    std::lock_guard lock(mLock);
+    mStopTimeNs = stopTimeNs;
+}
+
+bool Stream::requestStop(int32_t streamID)
+{
+    std::lock_guard lock(mLock);
+    if (streamID == mStreamID) {
+        if (mAudioTrack != nullptr) {
+            if (mState == PLAYING && !mMuted && (mLeftVolume != 0.f || mRightVolume != 0.f)) {
+                setVolume_l(0.f, 0.f);
+                mStopTimeNs = systemTime() + kStopWaitTimeNs;
+            } else {
+                mStopTimeNs = systemTime();
+            }
+            return true; // must be queued on the restart list.
+        }
+        stop_l();
+    }
+    return false;
+}
+
+void Stream::stop()
+{
+    std::lock_guard lock(mLock);
+    stop_l();
+}
+
+void Stream::stop_l()
+{
+    if (mState != IDLE) {
+        if (mAudioTrack != nullptr) {
+            mAudioTrack->stop();
+        }
+        mSound.reset();
+        mState = IDLE;
+    }
+}
+
+void Stream::clearAudioTrack()
+{
+    // This will invoke the destructor which waits for the AudioTrack thread to join,
+    // and is currently the only safe way to ensure there are no callbacks afterwards.
+    mAudioTrack.clear();
+}
+
+Stream* Stream::getPairStream() const
+{
+   return mStreamManager->getPairStream(this);
+}
+
+Stream* Stream::playPairStream() {
+    Stream* pairStream = getPairStream();
+    LOG_ALWAYS_FATAL_IF(pairStream == nullptr, "No pair stream!");
+    sp<AudioTrack> releaseTracks[2];
+    {
+        // TODO: Do we really want to force a simultaneous synchronization between
+        // the stream and its pair?
+
+        // note locking order - the paired stream is obtained before the queued stream.
+        // we can invert the locking order, but it is slightly more optimal to do it this way.
+        std::lock_guard lockp(pairStream->mLock);
+        if (pairStream->mSound == nullptr) {
+            return nullptr; // no pair sound
+        }
+        {
+            std::lock_guard lock(mLock);
+            LOG_ALWAYS_FATAL_IF(mState != IDLE, "State: %d must be IDLE", mState);
+            // TODO: do we want a specific set() here?
+            pairStream->mAudioTrack = mAudioTrack;
+            pairStream->mSoundID = mSoundID; // optimization to reuse AudioTrack.
+            pairStream->mToggle = mToggle;
+            pairStream->mAutoPaused = mAutoPaused; // save autopause state
+            pairStream->mMuted = mMuted;
+            mAudioTrack.clear();  // the pair owns the audiotrack.
+            mSound.reset();
+            mSoundID = 0;
+        }
+        // TODO: do we need a specific play_l() anymore?
+        const int pairState = pairStream->mState;
+        pairStream->play_l(pairStream->mSound, pairStream->mStreamID,
+                pairStream->mLeftVolume, pairStream->mRightVolume, pairStream->mPriority,
+                pairStream->mLoop, pairStream->mRate, releaseTracks);
+        if (pairStream->mState == IDLE) {
+            return nullptr; // AudioTrack error
+        }
+        if (pairState == PAUSED) {  // reestablish pause
+            pairStream->mState = PAUSED;
+            pairStream->mAudioTrack->pause();
+        }
+    }
+    // release tracks outside of Stream lock
+    return pairStream;
+}
+
+void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
+        float leftVolume, float rightVolume, int32_t priority, int32_t loop, float rate,
+        sp<AudioTrack> releaseTracks[2])
+{
+    // These tracks are released without the lock.
+    sp<AudioTrack> &oldTrack = releaseTracks[0];
+    sp<AudioTrack> &newTrack = releaseTracks[1];
+    status_t status = NO_ERROR;
+
+    {
+        ALOGV("%s(%p)(soundID=%d, streamID=%d, leftVolume=%f, rightVolume=%f,"
+                " priority=%d, loop=%d, rate=%f)",
+                __func__, this, sound->getSoundID(), nextStreamID, leftVolume, rightVolume,
+                priority, loop, rate);
+
+        // initialize track
+        const audio_stream_type_t streamType =
+                AudioSystem::attributesToStreamType(*mStreamManager->getAttributes());
+        const int32_t channelCount = sound->getChannelCount();
+        const uint32_t sampleRate = uint32_t(float(sound->getSampleRate()) * rate + 0.5);
+        size_t frameCount = 0;
+
+        if (loop) {
+            const audio_format_t format = sound->getFormat();
+            const size_t frameSize = audio_is_linear_pcm(format)
+                    ? channelCount * audio_bytes_per_sample(format) : 1;
+            frameCount = sound->getSizeInBytes() / frameSize;
+        }
+
+        // check if the existing track has the same sound id.
+        if (mAudioTrack != nullptr && mSoundID == sound->getSoundID()) {
+            // the sample rate may fail to change if the audio track is a fast track.
+            if (mAudioTrack->setSampleRate(sampleRate) == NO_ERROR) {
+                newTrack = mAudioTrack;
+                ALOGV("%s: reusing track %p for sound %d",
+                        __func__, mAudioTrack.get(), sound->getSoundID());
+            }
+        }
+        if (newTrack == 0) {
+            // mToggle toggles each time a track is started on a given stream.
+            // The toggle is concatenated with the Stream address and passed to AudioTrack
+            // as callback user data. This enables the detection of callbacks received from the old
+            // audio track while the new one is being started and avoids processing them with
+            // wrong audio audio buffer size  (mAudioBufferSize)
+            auto toggle = mToggle ^ 1;
+            void* userData = (void*)((uintptr_t)this | toggle);
+            audio_channel_mask_t soundChannelMask = sound->getChannelMask();
+            // When sound contains a valid channel mask, use it as is.
+            // Otherwise, use stream count to calculate channel mask.
+            audio_channel_mask_t channelMask = soundChannelMask != AUDIO_CHANNEL_NONE
+                    ? soundChannelMask : audio_channel_out_mask_from_count(channelCount);
+
+            // do not create a new audio track if current track is compatible with sound parameters
+
+            newTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
+                    channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
+                    staticCallback, userData,
+                    0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
+                    AudioTrack::TRANSFER_DEFAULT,
+                    nullptr /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/,
+                    mStreamManager->getAttributes());
+
+            oldTrack = mAudioTrack;
+            status = newTrack->initCheck();
+            if (status != NO_ERROR) {
+                ALOGE("%s: error creating AudioTrack", __func__);
+                // newTrack goes out of scope, so reference count drops to zero
+                goto exit;
+            }
+            // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
+            mToggle = toggle;
+            mAudioTrack = newTrack;
+            ALOGV("%s: using new track %p for sound %d",
+                    __func__, newTrack.get(), sound->getSoundID());
+        }
+        if (mMuted) {
+            newTrack->setVolume(0.0f, 0.0f);
+        } else {
+            newTrack->setVolume(leftVolume, rightVolume);
+        }
+        newTrack->setLoop(0, frameCount, loop);
+        mAudioTrack->start();
+        mSound = sound;
+        mSoundID = sound->getSoundID();
+        mPriority = priority;
+        mLoop = loop;
+        mLeftVolume = leftVolume;
+        mRightVolume = rightVolume;
+        mRate = rate;
+        mState = PLAYING;
+        mStopTimeNs = 0;
+        mStreamID = nextStreamID;  // prefer this to be the last, as it is an atomic sync point
+    }
+
+exit:
+    ALOGV("%s: delete oldTrack %p", __func__, oldTrack.get());
+    if (status != NO_ERROR) {
+        // TODO: should we consider keeping the soundID if the old track is OK?
+        // Do not attempt to restart this track (should we remove the stream id?)
+        mState = IDLE;
+        mSoundID = 0;
+        mSound.reset();
+        mAudioTrack.clear();  // actual release from releaseTracks[]
+    }
+}
+
+/* static */
+void Stream::staticCallback(int event, void* user, void* info)
+{
+    const uintptr_t userAsInt = (uintptr_t)user;
+    Stream* stream = reinterpret_cast<Stream*>(userAsInt & ~1);
+    stream->callback(event, info, userAsInt & 1, 0 /* tries */);
+}
+
+void Stream::callback(int event, void* info, int toggle, int tries)
+{
+    ALOGV("%s streamID %d", __func__, (int)mStreamID);
+    int32_t activeStreamIDToRestart = 0;
+    {
+        std::unique_lock lock(mLock);
+
+        if (mAudioTrack == nullptr) {
+            // The AudioTrack is either with this stream or its pair.
+            // if this swaps a few times, the toggle is bound to be wrong, so we fail then.
+            //
+            // TODO: Modify AudioTrack callbacks to avoid the hacky toggle and retry
+            // logic here.
+            if (tries < 3) {
+                lock.unlock();
+                getPairStream()->callback(event, info, toggle, tries + 1);
+            } else {
+                ALOGW("%s streamID %d cannot find track", __func__, (int)mStreamID);
+            }
+            return;
+        }
+        if (mToggle != toggle) {
+            ALOGD("%s streamID %d wrong toggle", __func__, (int)mStreamID);
+            return;
+        }
+        switch (event) {
+        case AudioTrack::EVENT_MORE_DATA:
+            ALOGW("%s streamID %d Invalid EVENT_MORE_DATA for static track",
+                    __func__, (int)mStreamID);
+            break;
+        case AudioTrack::EVENT_UNDERRUN:
+            ALOGW("%s streamID %d Invalid EVENT_UNDERRUN for static track",
+                    __func__, (int)mStreamID);
+            break;
+        case AudioTrack::EVENT_BUFFER_END:
+            ALOGV("%s streamID %d EVENT_BUFFER_END", __func__, (int)mStreamID);
+            if (mState != IDLE) {
+                activeStreamIDToRestart = mStreamID;
+                mStopTimeNs = systemTime();
+            }
+            break;
+        case AudioTrack::EVENT_LOOP_END:
+            ALOGV("%s streamID %d EVENT_LOOP_END", __func__, (int)mStreamID);
+            break;
+        case AudioTrack::EVENT_NEW_IAUDIOTRACK:
+            ALOGV("%s streamID %d NEW_IAUDIOTRACK", __func__, (int)mStreamID);
+            break;
+        default:
+            ALOGW("%s streamID %d Invalid event %d", __func__, (int)mStreamID, event);
+            break;
+        }
+    } // lock ends here.  This is on the callback thread, no need to be precise.
+    if (activeStreamIDToRestart > 0) {
+        // Restart only if a particular streamID is still current and active.
+        ALOGV("%s: moveToRestartQueue %d", __func__, activeStreamIDToRestart);
+        mStreamManager->moveToRestartQueue(this, activeStreamIDToRestart);
+    }
+}
+
+void Stream::dump() const
+{
+    ALOGV("mPairStream=%p, mState=%d, mStreamID=%d, mSoundID=%d, mPriority=%d, mLoop=%d",
+            getPairStream(), mState, (int)mStreamID, mSoundID, mPriority, mLoop);
+}
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/Stream.h b/media/jni/soundpool/Stream.h
new file mode 100644
index 0000000..82d2690
--- /dev/null
+++ b/media/jni/soundpool/Stream.h
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Sound.h"
+
+#include <audio_utils/clock.h>
+#include <media/AudioTrack.h>
+
+namespace android::soundpool {
+
+// This is the amount of time to wait after stop is called when stealing an
+// AudioTrack to allow the sound to ramp down.  If this is 0, glitches
+// may occur when stealing an AudioTrack.
+inline constexpr int64_t kStopWaitTimeNs = 20 * NANOS_PER_MILLISECOND;
+
+inline constexpr size_t kCacheLineSize = 64; /* std::hardware_constructive_interference_size */
+
+class StreamManager; // forward decl
+
+/**
+ * A Stream is associated with a StreamID exposed to the app to play a Sound.
+ *
+ * The Stream uses monitor locking strategy on mLock.
+ * https://en.wikipedia.org/wiki/Monitor_(synchronization)
+ *
+ * where public methods are guarded by a lock (as needed)
+ *
+ * For Java equivalent APIs, see
+ * https://developer.android.com/reference/android/media/SoundPool
+ *
+ * Streams are paired by the StreamManager, so one stream in the pair may be "stopping"
+ * while the other stream of the pair has been prepared to run
+ * (and the streamID returned to the app) pending its pair to be stopped.
+ * The pair of a Stream may be obtained by calling getPairStream(),
+ * where this->getPairStream()->getPairStream() == this; (pair is a commutative relationship).
+ *
+ * playPairStream() and getPairPriority() access the paired stream.
+ * See also StreamManager.h for details of physical layout implications of paired streams.
+ */
+class alignas(kCacheLineSize) Stream {
+public:
+    enum state { IDLE, PAUSED, PLAYING };
+    // The PAUSED, PLAYING state directly corresponds to the AudioTrack state of an active Stream.
+    //
+    // The IDLE state indicates an inactive Stream.   An IDLE Stream may have a non-nullptr
+    // AudioTrack, which may be recycled for use if the SoundID matches the next Stream playback.
+    //
+    // PAUSED -> PLAYING through resume()  (see also autoResume())
+    // PLAYING -> PAUSED through pause()   (see also autoPause())
+    //
+    // IDLE is the initial state of a Stream and also when a stream becomes inactive.
+    // {PAUSED, PLAYING} -> IDLE through stop() (or if the Sound finishes playing)
+    // IDLE -> PLAYING through play().  (there is no way to start a Stream in paused mode).
+
+    ~Stream();
+    void setStreamManager(StreamManager* streamManager) { // non-nullptr
+        mStreamManager = streamManager; // set in StreamManager constructor, not changed
+    }
+
+    // The following methods are monitor locked by mLock.
+    //
+    // For methods taking a streamID:
+    // if the streamID matches the Stream's mStreamID, then method proceeds
+    // else the command is ignored with no effect.
+
+    // returns true if the stream needs to be explicitly stopped.
+    bool requestStop(int32_t streamID);
+    void stop();                    // explicit stop(), typically called from the worker thread.
+    void clearAudioTrack();
+    void pause(int32_t streamID);
+    void autoPause();               // see the Java SoundPool.autoPause documentation for details.
+    void resume(int32_t streamID);
+    void autoResume();
+    void mute(bool muting);
+    void dump() const;
+
+    // returns the pair stream if successful, nullptr otherwise
+    Stream* playPairStream();
+
+    // These parameters are explicitly checked in the SoundPool class
+    // so never deviate from the Java API specified values.
+    void setVolume(int32_t streamID, float leftVolume, float rightVolume);
+    void setRate(int32_t streamID, float rate);
+    void setPriority(int32_t streamID, int priority);
+    void setLoop(int32_t streamID, int loop);
+    void setPlay(int32_t streamID, const std::shared_ptr<Sound> &sound, int32_t soundID,
+           float leftVolume, float rightVolume, int32_t priority, int32_t loop, float rate);
+    void setStopTimeNs(int64_t stopTimeNs); // systemTime() clock monotonic.
+
+    // The following getters are not locked and have weak consistency.
+    // These are considered advisory only - being stale is of nuisance.
+    int32_t getPriority() const { return mPriority; }
+    int32_t getPairPriority() const { return getPairStream()->getPriority(); }
+    int64_t getStopTimeNs() const { return mStopTimeNs; }
+
+    int32_t getStreamID() const { return mStreamID; }  // Can change with setPlay()
+    int32_t getSoundID() const { return mSoundID; }    // Can change with play_l()
+    bool hasSound() const { return mSound.get() != nullptr; }
+
+    Stream* getPairStream() const;  // this never changes.  See top of header.
+
+private:
+    void play_l(const std::shared_ptr<Sound>& sound, int streamID,
+            float leftVolume, float rightVolume, int priority, int loop, float rate,
+            sp<AudioTrack> releaseTracks[2]);
+    void stop_l();
+    void setVolume_l(float leftVolume, float rightVolume);
+
+    // For use with AudioTrack callback.
+    static void staticCallback(int event, void* user, void* info);
+    void callback(int event, void* info, int toggle, int tries);
+
+    // StreamManager should be set on construction and not changed.
+    // release mLock before calling into StreamManager
+    StreamManager*     mStreamManager = nullptr;
+
+    mutable std::mutex  mLock;
+    std::atomic_int32_t mStreamID = 0;          // Note: valid streamIDs are always positive.
+    int                 mState = IDLE;
+    std::shared_ptr<Sound> mSound;              // Non-null if playing.
+    int32_t             mSoundID = 0;           // The sound ID associated with the AudioTrack.
+    float               mLeftVolume = 0.f;
+    float               mRightVolume = 0.f;
+    int32_t             mPriority = INT32_MIN;
+    int32_t             mLoop = 0;
+    float               mRate = 0.f;
+    bool                mAutoPaused = false;
+    bool                mMuted = false;
+
+    sp<AudioTrack>      mAudioTrack;
+    int                 mToggle = 0;
+    int64_t             mStopTimeNs = 0;        // if nonzero, time to wait for stop.
+};
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
new file mode 100644
index 0000000..8928c47
--- /dev/null
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -0,0 +1,407 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool::StreamManager"
+#include <utils/Log.h>
+
+#include "StreamManager.h"
+
+#include <audio_utils/clock.h>
+#include <audio_utils/roundup.h>
+
+namespace android::soundpool {
+
+// kMaxStreams is number that should be less than the current AudioTrack max per UID of 40.
+// It is the maximum number of AudioTrack resources allowed in the SoundPool.
+// We suggest a value at least 4 or greater to allow CTS tests to pass.
+static constexpr int32_t kMaxStreams = 32;
+
+// kStealActiveStream_OldestFirst = false historically (Q and earlier)
+// Changing to true could break app expectations but could change behavior beneficially.
+// In R, we change this to true, as it is the correct way per SoundPool documentation.
+static constexpr bool kStealActiveStream_OldestFirst = true;
+
+// kPlayOnCallingThread = true prior to R.
+// Changing to false means calls to play() are almost instantaneous instead of taking around
+// ~10ms to launch the AudioTrack. It is perhaps 100x faster.
+static constexpr bool kPlayOnCallingThread = false;
+
+// Amount of time for a StreamManager thread to wait before closing.
+static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND;
+
+////////////
+
+StreamMap::StreamMap(int32_t streams) {
+    ALOGV("%s(%d)", __func__, streams);
+    if (streams > kMaxStreams) {
+        ALOGW("%s: requested %d streams, clamping to %d", __func__, streams, kMaxStreams);
+        streams = kMaxStreams;
+    } else if (streams < 1) {
+        ALOGW("%s: requested %d streams, clamping to 1", __func__, streams);
+        streams = 1;
+    }
+    mStreamPoolSize = streams * 2;
+    mStreamPool.reset(new Stream[mStreamPoolSize]);
+    // we use a perfect hash table with 2x size to map StreamIDs to Stream pointers.
+    mPerfectHash = std::make_unique<PerfectHash<int32_t, Stream *>>(roundup(mStreamPoolSize * 2));
+}
+
+Stream* StreamMap::findStream(int32_t streamID) const
+{
+    Stream *stream = lookupStreamFromId(streamID);
+    return stream != nullptr && stream->getStreamID() == streamID ? stream : nullptr;
+}
+
+size_t StreamMap::streamPosition(const Stream* stream) const
+{
+    ptrdiff_t index = stream - mStreamPool.get();
+    LOG_ALWAYS_FATAL_IF(index < 0 || index >= mStreamPoolSize,
+            "%s: stream position out of range: %td", __func__, index);
+    return (size_t)index;
+}
+
+Stream* StreamMap::lookupStreamFromId(int32_t streamID) const
+{
+    return streamID > 0 ? mPerfectHash->getValue(streamID).load() : nullptr;
+}
+
+int32_t StreamMap::getNextIdForStream(Stream* stream) const {
+    // even though it is const, it mutates the internal hash table.
+    const int32_t id = mPerfectHash->generateKey(
+        stream,
+        [] (Stream *stream) {
+            return stream == nullptr ? 0 : stream->getStreamID();
+        }, /* getKforV() */
+        stream->getStreamID() /* oldID */);
+    return id;
+}
+
+////////////
+
+StreamManager::StreamManager(
+        int32_t streams, size_t threads, const audio_attributes_t* attributes)
+    : StreamMap(streams)
+    , mAttributes(*attributes)
+{
+    ALOGV("%s(%d, %zu, ...)", __func__, streams, threads);
+    forEach([this](Stream *stream) {
+        stream->setStreamManager(this);
+        if ((streamPosition(stream) & 1) == 0) { // put the first stream of pair as available.
+            mAvailableStreams.insert(stream);
+        }
+    });
+
+    mThreadPool = std::make_unique<ThreadPool>(
+            std::min(threads, (size_t)std::thread::hardware_concurrency()),
+            "SoundPool_");
+}
+
+StreamManager::~StreamManager()
+{
+    ALOGV("%s", __func__);
+    {
+        std::unique_lock lock(mStreamManagerLock);
+        mQuit = true;
+        mStreamManagerCondition.notify_all();
+    }
+    mThreadPool->quit();
+
+    // call stop on the stream pool
+    forEach([](Stream *stream) { stream->stop(); });
+
+    // This invokes the destructor on the AudioTracks -
+    // we do it here to ensure that AudioTrack callbacks will not occur
+    // afterwards.
+    forEach([](Stream *stream) { stream->clearAudioTrack(); });
+}
+
+
+int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
+        int32_t soundID, float leftVolume, float rightVolume,
+        int32_t priority, int32_t loop, float rate)
+{
+    ALOGV("%s(sound=%p, soundID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f)",
+            __func__, sound.get(), soundID, leftVolume, rightVolume, priority, loop, rate);
+    bool launchThread = false;
+    int32_t streamID = 0;
+
+    { // for lock
+        std::unique_lock lock(mStreamManagerLock);
+        Stream *newStream = nullptr;
+        bool fromAvailableQueue = false;
+        ALOGV("%s: mStreamManagerLock lock acquired", __func__);
+
+        sanityCheckQueue_l();
+        // find an available stream, prefer one that has matching sound id.
+        if (mAvailableStreams.size() > 0) {
+            newStream = *mAvailableStreams.begin();
+            for (auto stream : mAvailableStreams) {
+                if (stream->getSoundID() == soundID) {
+                    newStream = stream;
+                    break;
+                }
+            }
+            if (newStream != nullptr) {
+                newStream->setStopTimeNs(systemTime());
+            }
+            fromAvailableQueue = true;
+        }
+
+        // also look in the streams restarting (if the paired stream doesn't have a pending play)
+        if (newStream == nullptr || newStream->getSoundID() != soundID) {
+            for (auto [unused , stream] : mRestartStreams) {
+                if (!stream->getPairStream()->hasSound()) {
+                    if (stream->getSoundID() == soundID) {
+                        newStream = stream;
+                        break;
+                    } else if (newStream == nullptr) {
+                        newStream = stream;
+                    }
+                }
+            }
+        }
+
+        // no available streams, look for one to steal from the active list
+        if (newStream == nullptr) {
+            for (auto stream : mActiveStreams) {
+                if (stream->getPriority() <= priority) {
+                    if (newStream == nullptr
+                            || newStream->getPriority() > stream->getPriority()) {
+                        newStream = stream;
+                    }
+                }
+            }
+            if (newStream != nullptr) { // we need to mute as it is still playing.
+                (void)newStream->requestStop(newStream->getStreamID());
+            }
+        }
+
+        // none found, look for a stream that is restarting, evict one.
+        if (newStream == nullptr) {
+            for (auto [unused, stream] : mRestartStreams) {
+                if (stream->getPairPriority() <= priority) {
+                    newStream = stream;
+                    break;
+                }
+            }
+        }
+
+        // DO NOT LOOK into mProcessingStreams as those are held by the StreamManager threads.
+
+        if (newStream == nullptr) {
+            ALOGD("%s: unable to find stream, returning 0", __func__);
+            return 0; // unable to find available stream
+        }
+
+        Stream *pairStream = newStream->getPairStream();
+        streamID = getNextIdForStream(pairStream);
+        pairStream->setPlay(
+                streamID, sound, soundID, leftVolume, rightVolume, priority, loop, rate);
+        if (fromAvailableQueue && kPlayOnCallingThread) {
+            removeFromQueues_l(newStream);
+            mProcessingStreams.emplace(newStream);
+            lock.unlock();
+            if (Stream* nextStream = newStream->playPairStream()) {
+                lock.lock();
+                ALOGV("%s: starting streamID:%d", __func__, nextStream->getStreamID());
+                addToActiveQueue_l(nextStream);
+            } else {
+                lock.lock();
+                mAvailableStreams.insert(newStream);
+                streamID = 0;
+            }
+            mProcessingStreams.erase(newStream);
+        } else {
+            launchThread = moveToRestartQueue_l(newStream) && needMoreThreads_l();
+        }
+        sanityCheckQueue_l();
+        ALOGV("%s: mStreamManagerLock released", __func__);
+    } // lock
+
+    if (launchThread) {
+        const int32_t id __unused = mThreadPool->launch([this](int32_t id) { run(id); });
+        ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id);
+    }
+    ALOGV("%s: returning %d", __func__, streamID);
+    return streamID;
+}
+
+void StreamManager::moveToRestartQueue(
+        Stream* stream, int32_t activeStreamIDToMatch)
+{
+    ALOGV("%s(stream(ID)=%d, activeStreamIDToMatch=%d)",
+            __func__, stream->getStreamID(), activeStreamIDToMatch);
+    bool restart;
+    {
+        std::lock_guard lock(mStreamManagerLock);
+        sanityCheckQueue_l();
+        if (mProcessingStreams.count(stream) > 0 ||
+                mProcessingStreams.count(stream->getPairStream()) > 0) {
+            ALOGD("%s: attempting to restart processing stream(%d)",
+                    __func__, stream->getStreamID());
+            restart = false;
+        } else {
+            moveToRestartQueue_l(stream, activeStreamIDToMatch);
+            restart = needMoreThreads_l();
+        }
+        sanityCheckQueue_l();
+    }
+    if (restart) {
+        const int32_t id __unused = mThreadPool->launch([this](int32_t id) { run(id); });
+        ALOGV_IF(id != 0, "%s: launched thread %d", __func__, id);
+    }
+}
+
+bool StreamManager::moveToRestartQueue_l(
+        Stream* stream, int32_t activeStreamIDToMatch)
+{
+    ALOGV("%s(stream(ID)=%d, activeStreamIDToMatch=%d)",
+            __func__, stream->getStreamID(), activeStreamIDToMatch);
+    if (activeStreamIDToMatch > 0 && stream->getStreamID() != activeStreamIDToMatch) {
+        return false;
+    }
+    const ssize_t found = removeFromQueues_l(stream, activeStreamIDToMatch);
+    if (found < 0) return false;
+
+    LOG_ALWAYS_FATAL_IF(found > 1, "stream on %zd > 1 stream lists", found);
+
+    addToRestartQueue_l(stream);
+    mStreamManagerCondition.notify_one();
+    return true;
+}
+
+ssize_t StreamManager::removeFromQueues_l(
+        Stream* stream, int32_t activeStreamIDToMatch) {
+    size_t found = 0;
+    for (auto it = mActiveStreams.begin(); it != mActiveStreams.end(); ++it) {
+        if (*it == stream) {
+            mActiveStreams.erase(it); // we erase the iterator and break (otherwise it not safe).
+            ++found;
+            break;
+        }
+    }
+    // activeStreamIDToMatch is nonzero indicates we proceed only if found.
+    if (found == 0 && activeStreamIDToMatch > 0) {
+        return -1;  // special code: not present on active streams, ignore restart request
+    }
+
+    for (auto it = mRestartStreams.begin(); it != mRestartStreams.end(); ++it) {
+        if (it->second == stream) {
+            mRestartStreams.erase(it);
+            ++found;
+            break;
+        }
+    }
+    found += mAvailableStreams.erase(stream);
+
+    // streams on mProcessingStreams are undergoing processing by the StreamManager thread
+    // and do not participate in normal stream migration.
+    return found;
+}
+
+void StreamManager::addToRestartQueue_l(Stream *stream) {
+    mRestartStreams.emplace(stream->getStopTimeNs(), stream);
+}
+
+void StreamManager::addToActiveQueue_l(Stream *stream) {
+    if (kStealActiveStream_OldestFirst) {
+        mActiveStreams.push_back(stream);  // oldest to newest
+    } else {
+        mActiveStreams.push_front(stream); // newest to oldest
+    }
+}
+
+void StreamManager::run(int32_t id)
+{
+    ALOGV("%s(%d) entering", __func__, id);
+    int64_t waitTimeNs = kWaitTimeBeforeCloseNs;
+    std::unique_lock lock(mStreamManagerLock);
+    while (!mQuit) {
+        mStreamManagerCondition.wait_for(
+                lock, std::chrono::duration<int64_t, std::nano>(waitTimeNs));
+        ALOGV("%s(%d) awake", __func__, id);
+
+        sanityCheckQueue_l();
+
+        if (mQuit || (mRestartStreams.empty() && waitTimeNs == kWaitTimeBeforeCloseNs)) {
+            break;  // end the thread
+        }
+
+        waitTimeNs = kWaitTimeBeforeCloseNs;
+        while (!mQuit && !mRestartStreams.empty()) {
+            const nsecs_t nowNs = systemTime();
+            auto it = mRestartStreams.begin();
+            Stream* const stream = it->second;
+            const int64_t diffNs = stream->getStopTimeNs() - nowNs;
+            if (diffNs > 0) {
+                waitTimeNs = std::min(waitTimeNs, diffNs);
+                break;
+            }
+            mRestartStreams.erase(it);
+            mProcessingStreams.emplace(stream);
+            lock.unlock();
+            stream->stop();
+            ALOGV("%s(%d) stopping streamID:%d", __func__, id, stream->getStreamID());
+            if (Stream* nextStream = stream->playPairStream()) {
+                ALOGV("%s(%d) starting streamID:%d", __func__, id, nextStream->getStreamID());
+                lock.lock();
+                if (nextStream->getStopTimeNs() > 0) {
+                    // the next stream was stopped before we can move it to the active queue.
+                    ALOGV("%s(%d) stopping started streamID:%d",
+                            __func__, id, nextStream->getStreamID());
+                    moveToRestartQueue_l(nextStream);
+                } else {
+                    addToActiveQueue_l(nextStream);
+                }
+            } else {
+                lock.lock();
+                mAvailableStreams.insert(stream);
+            }
+            mProcessingStreams.erase(stream);
+            sanityCheckQueue_l();
+        }
+    }
+    ALOGV("%s(%d) exiting", __func__, id);
+}
+
+void StreamManager::dump() const
+{
+    forEach([](const Stream *stream) { stream->dump(); });
+}
+
+void StreamManager::sanityCheckQueue_l() const
+{
+    // We want to preserve the invariant that each stream pair is exactly on one of the queues.
+    const size_t availableStreams = mAvailableStreams.size();
+    const size_t restartStreams = mRestartStreams.size();
+    const size_t activeStreams = mActiveStreams.size();
+    const size_t processingStreams = mProcessingStreams.size();
+    const size_t managedStreams = availableStreams + restartStreams + activeStreams
+                + processingStreams;
+    const size_t totalStreams = getStreamMapSize() >> 1;
+    LOG_ALWAYS_FATAL_IF(managedStreams != totalStreams,
+            "%s: mAvailableStreams:%zu + mRestartStreams:%zu + "
+            "mActiveStreams:%zu + mProcessingStreams:%zu = %zu != total streams %zu",
+            __func__, availableStreams, restartStreams, activeStreams, processingStreams,
+            managedStreams, totalStreams);
+    ALOGV("%s: mAvailableStreams:%zu + mRestartStreams:%zu + "
+            "mActiveStreams:%zu + mProcessingStreams:%zu = %zu (total streams: %zu)",
+            __func__, availableStreams, restartStreams, activeStreams, processingStreams,
+            managedStreams, totalStreams);
+}
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
new file mode 100644
index 0000000..8c98ac9
--- /dev/null
+++ b/media/jni/soundpool/StreamManager.h
@@ -0,0 +1,467 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Stream.h"
+
+#include <condition_variable>
+#include <future>
+#include <list>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <unordered_set>
+#include <vector>
+
+#include <utils/AndroidThreads.h>
+
+namespace android::soundpool {
+
+// TODO: Move helper classes to a utility file, with separate test.
+
+/**
+ * JavaThread is used like std::thread but for threads that may call the JVM.
+ *
+ * std::thread does not easily attach to the JVM.  We need JVM capable threads
+ * from createThreadEtc() since android binder call optimization may attempt to
+ * call back into Java if the SoundPool runs in system server.
+ *
+ *
+ * No locking is required - the member variables are inherently thread-safe.
+ */
+class JavaThread {
+public:
+    JavaThread(std::function<void()> f, const char *name)
+        : mF{std::move(f)} {
+        createThreadEtc(staticFunction, this, name);
+    }
+
+    JavaThread(JavaThread &&) = delete; // uses "this" ptr, not moveable.
+
+    void join() const {
+        mFuture.wait();
+    }
+
+    bool isClosed() const {
+        return mIsClosed;
+    }
+
+private:
+    static int staticFunction(void *data) {
+        JavaThread *jt = static_cast<JavaThread *>(data);
+        jt->mF();
+        jt->mIsClosed = true;
+        jt->mPromise.set_value();
+        return 0;
+    }
+
+    // No locking is provided as these variables are initialized in the constructor
+    // and the members referenced are thread-safe objects.
+    // (mFuture.wait() can block multiple threads.)
+    // Note the order of member variables is reversed for destructor.
+    const std::function<void()> mF;
+    // Used in join() to block until the thread completes.
+    // See https://en.cppreference.com/w/cpp/thread/promise for the void specialization of
+    // promise.
+    std::promise<void>          mPromise;
+    std::future<void>           mFuture{mPromise.get_future()};
+    std::atomic_bool            mIsClosed = false;
+};
+
+/**
+ * The ThreadPool manages thread lifetimes of SoundPool worker threads.
+ *
+ * TODO: the (eventual) goal of ThreadPool is to transparently and cooperatively
+ * maximize CPU utilization while avoiding starvation of other applications.
+ * Some possibilities:
+ *
+ * We should create worker threads when we have SoundPool work and the system is idle.
+ * CPU cycles are "use-it-or-lose-it" when the system is idle.
+ *
+ * We should adjust the priority of worker threads so that the second (and subsequent) worker
+ * threads have lower priority (should we try to promote priority also?).
+ *
+ * We should throttle the spawning of new worker threads, spacing over time, to avoid
+ * creating too many new threads all at once, on initialization.
+ */
+class ThreadPool {
+public:
+    ThreadPool(size_t maxThreadCount, std::string name)
+        : mMaxThreadCount(maxThreadCount)
+        , mName{std::move(name)} { }
+
+    ~ThreadPool() { quit(); }
+
+    size_t getActiveThreadCount() const { return mActiveThreadCount; }
+    size_t getMaxThreadCount() const { return mMaxThreadCount; }
+
+    void quit() {
+        std::list<std::unique_ptr<JavaThread>> threads;
+        {
+            std::lock_guard lock(mThreadLock);
+            if (mQuit) return;  // already joined.
+            mQuit = true;
+            threads = std::move(mThreads);
+            mThreads.clear();
+        }
+        // mQuit set under lock, no more threads will be created.
+        for (auto &thread : threads) {
+            thread->join();
+            thread.reset();
+        }
+        LOG_ALWAYS_FATAL_IF(mActiveThreadCount != 0,
+                "Invalid Active Threads: %zu", (size_t)mActiveThreadCount);
+    }
+
+    // returns a non-zero id if successful, the id is to help logging messages.
+    int32_t launch(std::function<void(int32_t /* id */)> f) {
+        std::list<std::unique_ptr<JavaThread>> threadsToRelease; // release outside of lock.
+        std::lock_guard lock(mThreadLock);
+        if (mQuit) return 0;  // ignore if we have quit
+
+        // clean up threads.
+        for (auto it = mThreads.begin(); it != mThreads.end(); ) {
+            if ((*it)->isClosed()) {
+                threadsToRelease.emplace_back(std::move(*it));
+               it = mThreads.erase(it);
+            } else {
+               ++it;
+            }
+        }
+
+        const size_t threadCount = mThreads.size();
+        if (threadCount < mMaxThreadCount) {
+            // if the id wraps, we don't care about collisions.  it's just for logging.
+            mNextThreadId = mNextThreadId == INT32_MAX ? 1 : ++mNextThreadId;
+            const int32_t id = mNextThreadId;
+            mThreads.emplace_back(std::make_unique<JavaThread>(
+                    [this, id, mf = std::move(f)] { mf(id); --mActiveThreadCount; },
+                    (mName + std::to_string(id)).c_str()));
+            ++mActiveThreadCount;
+            return id;
+        }
+        return 0;
+    }
+
+    // TODO: launch only if load average is low.
+    // This gets the load average
+    // See also std::thread::hardware_concurrency() for the concurrent capability.
+    static double getLoadAvg() {
+        double loadAvg[1];
+        if (getloadavg(loadAvg, std::size(loadAvg)) > 0) {
+            return loadAvg[0];
+        }
+        return -1.;
+    }
+
+private:
+    const size_t            mMaxThreadCount;
+    const std::string       mName;
+
+    std::atomic_size_t      mActiveThreadCount = 0;
+
+    std::mutex              mThreadLock;
+    bool                    mQuit = false;           // GUARDED_BY(mThreadLock)
+    int32_t                 mNextThreadId = 0;       // GUARDED_BY(mThreadLock)
+    std::list<std::unique_ptr<JavaThread>> mThreads; // GUARDED_BY(mThreadLock)
+};
+
+/**
+ * A Perfect HashTable for IDs (key) to pointers (value).
+ *
+ * There are no collisions.  Why? because we generate the IDs for you to look up :-).
+ *
+ * The goal of this hash table is to map an integer ID handle > 0 to a pointer.
+ * We give these IDs in monotonic order (though we may skip if it were to cause a collision).
+ *
+ * The size of the hashtable must be large enough to accommodate the max number of keys.
+ * We suggest 2x.
+ *
+ * Readers are lockless
+ * Single writer could be lockless, but we allow multiple writers through an internal lock.
+ *
+ * For the Key type K, valid keys generated are > 0 (signed or unsigned)
+ * For the Value type V, values are pointers - nullptr means empty.
+ */
+template <typename K, typename V>
+class PerfectHash {
+public:
+    PerfectHash(size_t hashCapacity)
+        : mHashCapacity(hashCapacity)
+        , mK2V{new std::atomic<V>[hashCapacity]()} {
+    }
+
+    // Generate a key for a value V.
+    // There is a testing function getKforV() which checks what the value reports as its key.
+    //
+    // Calls back into getKforV under lock.
+    //
+    // We expect that the hashCapacity is 2x the number of stored keys in order
+    // to have one or two tries to find an empty slot
+    K generateKey(V value, std::function<K(V)> getKforV, K oldKey = 0) {
+        std::lock_guard lock(mHashLock);
+        // try to remove the old key.
+        if (oldKey > 0) {  // key valid
+            const V v = getValue(oldKey);
+            if (v != nullptr) {  // value still valid
+                const K atPosition = getKforV(v);
+                if (atPosition < 0 ||            // invalid value
+                        atPosition == oldKey ||  // value's key still valid and matches old key
+                        ((atPosition ^ oldKey) & (mHashCapacity - 1)) != 0) { // stale key entry
+                    getValue(oldKey) = nullptr;  // invalidate
+                }
+            } // else if value is invalid, no need to invalidate.
+        }
+        // check if we are invalidating only.
+        if (value == nullptr) return 0;
+        // now insert the new value and return the key.
+        size_t tries = 0;
+        for (; tries < mHashCapacity; ++tries) {
+            mNextKey = mNextKey == std::numeric_limits<K>::max() ? 1 : mNextKey + 1;
+            const V v = getValue(mNextKey);
+            //ALOGD("tries: %zu, key:%d value:%p", tries, (int)mNextKey, v);
+            if (v == nullptr) break; // empty
+            const K atPosition = getKforV(v);
+            //ALOGD("tries: %zu  key atPosition:%d", tries, (int)atPosition);
+            if (atPosition < 0 || // invalid value
+                    ((atPosition ^ mNextKey) & (mHashCapacity - 1)) != 0) { // stale key entry
+                break;
+           }
+        }
+        LOG_ALWAYS_FATAL_IF(tries == mHashCapacity, "hash table overflow!");
+        //ALOGD("%s: found after %zu tries", __func__, tries);
+        getValue(mNextKey) = value;
+        return mNextKey;
+    }
+
+    std::atomic<V> &getValue(K key) { return mK2V[key & (mHashCapacity - 1)]; }
+    const std::atomic_int32_t &getValue(K key) const { return mK2V[key & (mHashCapacity - 1)]; }
+
+private:
+    mutable std::mutex          mHashLock;
+    const size_t                mHashCapacity; // size of mK2V no lock needed.
+    std::unique_ptr<std::atomic<V>[]> mK2V;    // no lock needed for read access.
+    K                           mNextKey{};    // GUARDED_BY(mHashLock)
+};
+
+/**
+ * StreamMap contains the all the valid streams available to SoundPool.
+ *
+ * There is no Lock required for this class because the streams are
+ * allocated in the constructor, the lookup is lockless, and the Streams
+ * returned are locked internally.
+ *
+ * The lookup uses a perfect hash.
+ * It is possible to use a lockless hash table or to use a stripe-locked concurrent
+ * hashmap for essentially lock-free lookup.
+ *
+ * This follows Map-Reduce parallelism model.
+ * https://en.wikipedia.org/wiki/MapReduce
+ *
+ * Conceivably the forEach could be parallelized using std::for_each with a
+ * std::execution::par policy.
+ *
+ * https://en.cppreference.com/w/cpp/algorithm/for_each
+ */
+class StreamMap {
+public:
+    explicit StreamMap(int32_t streams);
+
+    // Returns the stream associated with streamID or nullptr if not found.
+    // This need not be locked.
+    // The stream ID will never migrate to another Stream, but it may change
+    // underneath you.  The Stream operations that take a streamID will confirm
+    // that the streamID matches under the Stream lock before executing otherwise
+    // it ignores the command as stale.
+    Stream* findStream(int32_t streamID) const;
+
+    // Iterates through the stream pool applying the function f.
+    // Since this enumerates over every single stream, it is unlocked.
+    //
+    // See related: https://en.cppreference.com/w/cpp/algorithm/for_each
+    void forEach(std::function<void(const Stream *)>f) const {
+        for (size_t i = 0; i < mStreamPoolSize; ++i) {
+            f(&mStreamPool[i]);
+        }
+    }
+
+    void forEach(std::function<void(Stream *)>f) {
+        for (size_t i = 0; i < mStreamPoolSize; ++i) {
+            f(&mStreamPool[i]);
+        }
+    }
+
+    // Returns the pair stream for a given Stream.
+    // This need not be locked as it is a property of the pointer address.
+    Stream* getPairStream(const Stream* stream) const {
+        const size_t index = streamPosition(stream);
+        return &mStreamPool[index ^ 1];
+    }
+
+    // find the position of the stream in mStreamPool array.
+    size_t streamPosition(const Stream* stream) const; // no lock needed
+
+    size_t getStreamMapSize() const {
+        return mStreamPoolSize;
+    }
+
+    // find the next valid ID for a stream and store in hash table.
+    int32_t getNextIdForStream(Stream* stream) const;
+
+private:
+
+    // use the hash table to attempt to find the stream.
+    // nullptr is returned if the lookup fails.
+    Stream* lookupStreamFromId(int32_t streamID) const;
+
+    // The stream pool is initialized in the constructor, effectively const.
+    // no locking required for access.
+    //
+    // The constructor parameter "streams" results in streams pairs of streams.
+    // We have twice as many streams because we wish to return a streamID "handle"
+    // back to the app immediately, while we may be stopping the other stream in the
+    // pair to get its AudioTrack :-).
+    //
+    // Of the stream pair, only one of the streams may have an AudioTrack.
+    // The fixed association of a stream pair allows callbacks from the AudioTrack
+    // to be associated properly to either one or the other of the stream pair.
+    //
+    // TODO: The stream pair arrangement can be removed if we have better AudioTrack
+    // callback handling (being able to remove and change the callback after construction).
+    //
+    // Streams may be accessed anytime off of the stream pool
+    // as there is internal locking on each stream.
+    std::unique_ptr<Stream[]>   mStreamPool;        // no lock needed for access.
+    size_t                      mStreamPoolSize;    // no lock needed for access.
+
+    // In order to find the Stream from a StreamID, we could do a linear lookup in mStreamPool.
+    // As an alternative, one could use stripe-locked or lock-free concurrent hashtables.
+    //
+    // When considering linear search vs hashmap, verify the typical use-case size.
+    // Linear search is faster than std::unordered_map (circa 2018) for less than 40 elements.
+    // [ Skarupke, M. (2018), "You Can Do Better than std::unordered_map: New and Recent
+    // Improvements to Hash Table Performance." C++Now 2018. cppnow.org, see
+    // https://www.youtube.com/watch?v=M2fKMP47slQ ]
+    //
+    // Here, we use a PerfectHash of Id to Stream *, since we can control the
+    // StreamID returned to the user.  This allows O(1) read access to mStreamPool lock-free.
+    //
+    // We prefer that the next stream ID is monotonic for aesthetic reasons
+    // (if we didn't care about monotonicity, a simple method is to apply a generation count
+    // to each stream in the unused upper bits of its index in mStreamPool for the id).
+    //
+    std::unique_ptr<PerfectHash<int32_t, Stream *>> mPerfectHash;
+};
+
+/**
+ * StreamManager is used to manage the streams (accessed by StreamID from Java).
+ *
+ * Locking order (proceeds from application to component).
+ *  SoundPool mApiLock (if needed) -> StreamManager mStreamManagerLock
+ *                                 -> pair Stream mLock -> queued Stream mLock
+ */
+class StreamManager : public StreamMap {
+public:
+    // Note: the SoundPool pointer is only used for stream initialization.
+    // It is not stored in StreamManager.
+    StreamManager(int32_t streams, size_t threads, const audio_attributes_t* attributes);
+    ~StreamManager();
+
+    // Returns positive streamID on success, 0 on failure.  This is locked.
+    int32_t queueForPlay(const std::shared_ptr<Sound> &sound,
+            int32_t soundID, float leftVolume, float rightVolume,
+            int32_t priority, int32_t loop, float rate);
+
+    ///////////////////////////////////////////////////////////////////////
+    // Called from soundpool::Stream
+
+    const audio_attributes_t* getAttributes() const { return &mAttributes; }
+
+    // Moves the stream to the restart queue (called upon BUFFER_END of the static track)
+    // this is locked internally.
+    // If activeStreamIDToMatch is nonzero, it will only move to the restart queue
+    // if the streamIDToMatch is found on the active queue.
+    void moveToRestartQueue(Stream* stream, int32_t activeStreamIDToMatch = 0);
+
+private:
+
+    void run(int32_t id);                        // worker thread, takes lock internally.
+    void dump() const;                           // no lock needed
+
+    // returns true if more worker threads are needed.
+    bool needMoreThreads_l() {
+        return mRestartStreams.size() > 0 &&
+                (mThreadPool->getActiveThreadCount() == 0
+                || std::distance(mRestartStreams.begin(),
+                        mRestartStreams.upper_bound(systemTime()))
+                        > (ptrdiff_t)mThreadPool->getActiveThreadCount());
+    }
+
+    // returns true if the stream was added.
+    bool moveToRestartQueue_l(Stream* stream, int32_t activeStreamIDToMatch = 0);
+    // returns number of queues the stream was removed from (should be 0 or 1);
+    // a special code of -1 is returned if activeStreamIDToMatch is > 0 and
+    // the stream wasn't found on the active queue.
+    ssize_t removeFromQueues_l(Stream* stream, int32_t activeStreamIDToMatch = 0);
+    void addToRestartQueue_l(Stream *stream);
+    void addToActiveQueue_l(Stream *stream);
+    void sanityCheckQueue_l() const;
+
+    const audio_attributes_t mAttributes;
+    std::unique_ptr<ThreadPool> mThreadPool;                  // locked internally
+
+    // mStreamManagerLock is used to lock access for transitions between the
+    // 4 stream queues by the Manager Thread or by the user initiated play().
+    // A stream pair has exactly one stream on exactly one of the queues.
+    std::mutex                  mStreamManagerLock;
+    std::condition_variable     mStreamManagerCondition;
+
+    bool                        mQuit = false;      // GUARDED_BY(mStreamManagerLock)
+
+    // There are constructor arg "streams" pairs of streams, only one of each
+    // pair on the 4 stream queues below.  The other stream in the pair serves as
+    // placeholder to accumulate user changes, pending actual availability of the
+    // AudioTrack, as it may be in use, requiring stop-then-restart.
+    //
+    // The 4 queues are implemented in the appropriate STL container based on perceived
+    // optimality.
+
+    // 1) mRestartStreams: Streams awaiting stop.
+    // The paired stream may be active (but with no AudioTrack), and will be restarted
+    // with an active AudioTrack when the current stream is stopped.
+    std::multimap<int64_t /* stopTimeNs */, Stream*>
+                                mRestartStreams;    // GUARDED_BY(mStreamManagerLock)
+
+    // 2) mActiveStreams: Streams that are active.
+    // The paired stream will be inactive.
+    // This is in order of specified by kStealActiveStream_OldestFirst
+    std::list<Stream*>          mActiveStreams;     // GUARDED_BY(mStreamManagerLock)
+
+    // 3) mAvailableStreams: Streams that are inactive.
+    // The paired stream will also be inactive.
+    // No particular order.
+    std::unordered_set<Stream*> mAvailableStreams;  // GUARDED_BY(mStreamManagerLock)
+
+    // 4) mProcessingStreams: Streams that are being processed by the ManagerThreads
+    // When on this queue, the stream and its pair are not available for stealing.
+    // Each ManagerThread will have at most one stream on the mProcessingStreams queue.
+    // The paired stream may be active or restarting.
+    // No particular order.
+    std::unordered_set<Stream*> mProcessingStreams; // GUARDED_BY(mStreamManagerLock)
+};
+
+} // namespace android::soundpool
diff --git a/media/jni/soundpool/tests/Android.bp b/media/jni/soundpool/tests/Android.bp
new file mode 100644
index 0000000..96ec4e5
--- /dev/null
+++ b/media/jni/soundpool/tests/Android.bp
@@ -0,0 +1,28 @@
+cc_binary {
+    name: "soundpool_stress",
+    host_supported: false,
+
+    include_dirs: [
+        "frameworks/base/media/jni/"
+    ],
+
+    shared_libs: [
+        "libaudioutils",
+        "libbinder",
+        "liblog",
+        "libmedia",
+        "libsoundpool",
+        "libstagefright",
+        "libutils",
+    ],
+
+    srcs: [
+        "soundpool_stress.cpp"
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
diff --git a/media/jni/soundpool/tests/build_and_run.sh b/media/jni/soundpool/tests/build_and_run.sh
new file mode 100755
index 0000000..741f2ef
--- /dev/null
+++ b/media/jni/soundpool/tests/build_and_run.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Run samples from this directory
+#
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+    echo "Android build environment not set"
+    exit -1
+fi
+
+# ensure we have mm
+. $ANDROID_BUILD_TOP/build/envsetup.sh
+
+mm
+
+echo "waiting for device"
+
+adb root && adb wait-for-device remount
+
+echo "========================================"
+echo "testing soundpool_stress"
+uidir="/product/media/audio/notifications"
+adb push $OUT/system/bin/soundpool_stress /system/bin
+
+# test SoundPool playback of all the UI sound samples (loaded twice) looping 10s 1 thread.
+#adb shell /system/bin/soundpool_stress -l -1 $uidir/*.ogg $uidir/*.ogg
+
+# performance test SoundPool playback of all the UI sound samples (x2)
+# 1 iterations, looping, 1 second playback, 4 threads.
+adb shell /system/bin/soundpool_stress -i 1 -l -1 -p 1 -t 4 $uidir/*.ogg $uidir/*.ogg
diff --git a/media/jni/soundpool/tests/soundpool_stress.cpp b/media/jni/soundpool/tests/soundpool_stress.cpp
new file mode 100644
index 0000000..212662f
--- /dev/null
+++ b/media/jni/soundpool/tests/soundpool_stress.cpp
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "soundpool"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include <atomic>
+#include <future>
+#include <mutex>
+#include <set>
+#include <vector>
+
+#include <audio_utils/clock.h>
+#include <binder/ProcessState.h>
+#include <media/stagefright/MediaExtractorFactory.h>
+#include <soundpool/SoundPool.h> // direct include, this is not an NDK feature.
+#include <system/audio.h>
+#include <utils/Log.h>
+
+using namespace android;
+
+// Errors and diagnostic messages all go to stdout.
+
+namespace {
+
+void usage(const char *name)
+{
+    printf("Usage: %s "
+            "[-i #iterations] [-l #loop] [-p #playback_seconds] [-s #streams] [-t #threads] "
+            "[-z #snoozeSec] <input-file>+\n", name);
+    printf("Uses soundpool to load and play a file (the first 10 seconds)\n");
+    printf("    -i #iterations, default 1\n");
+    printf("    -l #loop looping mode, -1 forever\n");
+    printf("    -p #playback_seconds, default 10\n");
+    printf("    -s #streams for concurrent sound playback, default 20\n");
+    printf("    -t #threads, default 1\n");
+    printf("    -z #snoozeSec after stopping, -1 forever, default 0\n");
+    printf("    <input-file>+ files to be played\n");
+}
+
+std::atomic_int32_t gErrors{};
+std::atomic_int32_t gWarnings{};
+
+void printEvent(const SoundPoolEvent *event) {
+    printf("{ msg:%d  id:%d  status:%d }\n", event->mMsg, event->mArg1, event->mArg2);
+}
+
+class CallbackManager {
+public:
+    int32_t getNumberEvents(int32_t soundID) {
+        std::lock_guard lock(mLock);
+        return mEvents[soundID] > 0;
+    }
+
+    void setSoundPool(SoundPool* soundPool) {
+        std::lock_guard lock(mLock);
+        mSoundPool = soundPool;
+    }
+
+    void callback(SoundPoolEvent event, const SoundPool *soundPool) {
+        std::lock_guard lock(mLock);
+        printEvent(&event);
+        if (soundPool != mSoundPool) {
+            printf("ERROR: mismatched soundpool: %p\n", soundPool);
+            ++gErrors;
+            return;
+        }
+        if (event.mMsg != 1 /* SoundPoolEvent::SOUND_LOADED */) {
+            printf("ERROR: invalid event msg: %d\n", event.mMsg);
+            ++gErrors;
+            return;
+        }
+        if (event.mArg2 != 0) {
+            printf("ERROR: event status(%d) != 0\n", event.mArg2);
+            ++gErrors;
+            return;
+        }
+        if (event.mArg1 <= 0) {
+            printf("ERROR: event soundID(%d) < 0\n", event.mArg1);
+            ++gErrors;
+            return;
+        }
+        ++mEvents[event.mArg1];
+    }
+
+private:
+    std::mutex mLock;
+    SoundPool *mSoundPool = nullptr;
+    std::map<int32_t /* soundID */, int32_t /* count */> mEvents;
+} gCallbackManager;
+
+
+void StaticCallbackManager(SoundPoolEvent event, SoundPool* soundPool, void* user) {
+    ((CallbackManager *)user)->callback(event, soundPool);
+}
+
+void testStreams(SoundPool *soundPool, const std::vector<const char *> &filenames,
+        int loop, int playSec)
+{
+    const int64_t startTimeNs = systemTime();
+    std::vector<int32_t> soundIDs;
+    for (auto filename : filenames) {
+        struct stat st;
+        if (stat(filename, &st) < 0) {
+            printf("ERROR: cannot stat %s\n", filename);
+            return;
+        }
+        const uint64_t length = uint64_t(st.st_size);
+        const int inp = open(filename, O_RDONLY);
+        if (inp < 0) {
+            printf("ERROR: cannot open %s\n", filename);
+            return;
+        }
+        printf("loading (%s) size (%llu)\n", filename, (unsigned long long)length);
+        const int32_t soundID = soundPool->load(
+                inp, 0 /*offset*/, length, 0 /*priority - unused*/);
+        if (soundID == 0) {
+            printf("ERROR: cannot load %s\n", filename);
+            return;
+        }
+        close(inp);
+        soundIDs.emplace_back(soundID);
+        printf("loaded %s soundID(%d)\n", filename, soundID);
+    }
+    const int64_t requestLoadTimeNs = systemTime();
+    printf("\nrequestLoadTimeMs: %d\n",
+            (int)((requestLoadTimeNs - startTimeNs) / NANOS_PER_MILLISECOND));
+
+    // create stream & get Id (playing)
+    const float maxVol = 1.f;
+    const float silentVol = 0.f;
+    const int priority = 0; // lowest
+    const float rate = 1.f;  // normal
+
+    // Loading is done by a SoundPool Worker thread.
+    // TODO: Use SoundPool::setCallback() for wait
+
+    for (int32_t soundID : soundIDs) {
+        while (true) {
+            const int32_t streamID =
+                    soundPool->play(soundID, silentVol, silentVol, priority, 0 /*loop*/, rate);
+            if (streamID != 0) {
+                const int32_t events = gCallbackManager.getNumberEvents(soundID);
+                if (events != 1) {
+                   printf("WARNING: successful play for streamID:%d soundID:%d"
+                          " but callback events(%d) != 1\n", streamID, soundID, events);
+                   ++gWarnings;
+                }
+                soundPool->stop(streamID);
+                break;
+            }
+            usleep(1000);
+        }
+        printf("[%d]", soundID);
+        fflush(stdout);
+    }
+
+    const int64_t loadTimeNs = systemTime();
+    printf("\nloadTimeMs: %d\n", (int)((loadTimeNs - startTimeNs) / NANOS_PER_MILLISECOND));
+
+    // check and play (overlap with above).
+    std::vector<int32_t> streamIDs;
+    for (int32_t soundID : soundIDs) {
+        printf("\nplaying soundID=%d", soundID);
+        const int32_t streamID = soundPool->play(soundID, maxVol, maxVol, priority, loop, rate);
+        if (streamID == 0) {
+            printf(" failed!  ERROR");
+            ++gErrors;
+        } else {
+            printf(" streamID=%d", streamID);
+            streamIDs.emplace_back(streamID);
+        }
+    }
+    const int64_t playTimeNs = systemTime();
+    printf("\nplayTimeMs: %d\n", (int)((playTimeNs - loadTimeNs) / NANOS_PER_MILLISECOND));
+
+    for (int i = 0; i < playSec; ++i) {
+        sleep(1);
+        printf(".");
+        fflush(stdout);
+    }
+
+    for (int32_t streamID : streamIDs) {
+        soundPool->stop(streamID);
+    }
+
+    for (int32_t soundID : soundIDs) {
+        soundPool->unload(soundID);
+    }
+    printf("\nDone!\n");
+}
+
+} // namespace
+
+int main(int argc, char *argv[])
+{
+    const char * const me = argv[0];
+
+    int iterations = 1;
+    int loop = 0;        // disable looping
+    int maxStreams = 40; // change to have more concurrent playback streams
+    int playSec = 10;
+    int snoozeSec = 0;
+    int threadCount = 1;
+    for (int ch; (ch = getopt(argc, argv, "i:l:p:s:t:z:")) != -1; ) {
+        switch (ch) {
+        case 'i':
+            iterations = atoi(optarg);
+            break;
+        case 'l':
+            loop = atoi(optarg);
+            break;
+        case 'p':
+            playSec = atoi(optarg);
+            break;
+        case 's':
+            maxStreams = atoi(optarg);
+            break;
+        case 't':
+            threadCount = atoi(optarg);
+            break;
+        case 'z':
+            snoozeSec = atoi(optarg);
+            break;
+        default:
+            usage(me);
+            return EXIT_FAILURE;
+        }
+    }
+
+    argc -= optind;
+    argv += optind;
+    if (argc <= 0) {
+        usage(me);
+        return EXIT_FAILURE;
+    }
+
+    std::vector<const char *> filenames(argv, argv + argc);
+
+    android::ProcessState::self()->startThreadPool();
+
+    // O and later requires data sniffer registration for proper file type detection
+    MediaExtractorFactory::LoadExtractors();
+
+    // create soundpool
+    audio_attributes_t aa = {
+        .content_type = AUDIO_CONTENT_TYPE_MUSIC,
+        .usage = AUDIO_USAGE_MEDIA,
+    };
+    auto soundPool = std::make_unique<SoundPool>(maxStreams, &aa);
+
+    gCallbackManager.setSoundPool(soundPool.get());
+    soundPool->setCallback(StaticCallbackManager, &gCallbackManager);
+
+    const int64_t startTimeNs = systemTime();
+
+    for (int it = 0; it < iterations; ++it) {
+        // One instance:
+        // testStreams(soundPool.get(), filenames, loop, playSec);
+
+        // Test multiple instances
+        std::vector<std::future<void>> threads(threadCount);
+        printf("testing %zu threads\n", threads.size());
+        for (auto &thread : threads) {
+            thread = std::async(std::launch::async,
+                    [&]{ testStreams(soundPool.get(), filenames, loop, playSec);});
+        }
+        // automatically joins.
+    }
+
+    const int64_t endTimeNs = systemTime();
+
+    // snooze before cleaning up to examine soundpool dumpsys state after stop
+    for (int i = 0; snoozeSec < 0 || i < snoozeSec; ++i) {
+        printf("z");
+        fflush(stdout);
+        sleep(1);
+    };
+
+    gCallbackManager.setSoundPool(nullptr);
+    soundPool.reset();
+
+    printf("total time in ms: %lld\n", (endTimeNs - startTimeNs) / NANOS_PER_MILLISECOND);
+    if (gWarnings != 0) {
+        printf("%d warnings!\n", gWarnings.load());
+    }
+    if (gErrors != 0) {
+        printf("%d errors!\n", gErrors.load());
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
index a0d2050..2da45b6 100644
--- a/media/native/midi/Android.bp
+++ b/media/native/midi/Android.bp
@@ -17,6 +17,7 @@
 
     srcs: [
         "amidi.cpp",
+        "MidiDeviceInfo.cpp",
         ":IMidiDeviceServer.aidl",
     ],
 
@@ -31,12 +32,14 @@
         "-fvisibility=hidden",
     ],
 
+    header_libs: [
+        "media_ndk_headers",
+    ],
+
     shared_libs: [
         "liblog",
         "libbinder",
         "libutils",
-        "libmedia",
-        "libmediandk",
         "libandroid_runtime",
     ],
 
diff --git a/media/native/midi/MidiDeviceInfo.cpp b/media/native/midi/MidiDeviceInfo.cpp
new file mode 100644
index 0000000..ac68d26
--- /dev/null
+++ b/media/native/midi/MidiDeviceInfo.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#define LOG_TAG "MidiDeviceInfo"
+
+#include <MidiDeviceInfo.h>
+
+#include <binder/Parcel.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+namespace media {
+namespace midi {
+
+// The constant values need to be kept in sync with MidiDeviceInfo.java.
+// static
+const char* const MidiDeviceInfo::PROPERTY_NAME = "name";
+const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
+const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
+const char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
+const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
+const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
+const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
+
+String16 MidiDeviceInfo::getProperty(const char* propertyName) {
+    String16 value;
+    if (mProperties.getString(String16(propertyName), &value)) {
+        return value;
+    } else {
+        return String16();
+    }
+}
+
+#define RETURN_IF_FAILED(calledOnce)                                     \
+    {                                                                    \
+        status_t returnStatus = calledOnce;                              \
+        if (returnStatus) {                                              \
+            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+            return returnStatus;                                         \
+         }                                                               \
+    }
+
+status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
+    // Needs to be kept in sync with code in MidiDeviceInfo.java
+    RETURN_IF_FAILED(parcel->writeInt32(mType));
+    RETURN_IF_FAILED(parcel->writeInt32(mId));
+    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
+    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
+    RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
+    RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
+    RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
+    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
+    // This corresponds to "extra" properties written by Java code
+    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
+    return OK;
+}
+
+status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
+    // Needs to be kept in sync with code in MidiDeviceInfo.java
+    RETURN_IF_FAILED(parcel->readInt32(&mType));
+    RETURN_IF_FAILED(parcel->readInt32(&mId));
+    int32_t inputPortCount;
+    RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
+    int32_t outputPortCount;
+    RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
+    RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
+    RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
+    int32_t isPrivate;
+    RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
+    mIsPrivate = isPrivate == 1;
+    RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
+    // Ignore "extra" properties as they may contain Java Parcelables
+    return OK;
+}
+
+status_t MidiDeviceInfo::readStringVector(
+        const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
+    std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
+    status_t result = parcel->readString16Vector(&v);
+    if (result != OK) return result;
+    vectorPtr->clear();
+    if (v.get() != nullptr) {
+        for (const auto& iter : *v) {
+            if (iter.get() != nullptr) {
+                vectorPtr->push_back(*iter);
+            } else {
+                vectorPtr->push_back(String16());
+            }
+        }
+    } else {
+        vectorPtr->resize(defaultLength);
+    }
+    return OK;
+}
+
+status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
+    std::vector<String16> v;
+    for (size_t i = 0; i < vector.size(); ++i) {
+        v.push_back(vector[i]);
+    }
+    return parcel->writeString16Vector(v);
+}
+
+// Vector does not define operator==
+static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
+    if (lhs.size() != rhs.size()) return false;
+    for (size_t i = 0; i < lhs.size(); ++i) {
+        if (lhs[i] != rhs[i]) return false;
+    }
+    return true;
+}
+
+bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
+    return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
+            areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
+            areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
+            lhs.mProperties == rhs.mProperties &&
+            lhs.mIsPrivate == rhs.mIsPrivate);
+}
+
+}  // namespace midi
+}  // namespace media
+}  // namespace android
diff --git a/media/native/midi/MidiDeviceInfo.h b/media/native/midi/MidiDeviceInfo.h
new file mode 100644
index 0000000..5b4a241
--- /dev/null
+++ b/media/native/midi/MidiDeviceInfo.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ANDROID_MEDIA_MIDI_DEVICE_INFO_H
+#define ANDROID_MEDIA_MIDI_DEVICE_INFO_H
+
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace media {
+namespace midi {
+
+class MidiDeviceInfo : public Parcelable {
+public:
+    MidiDeviceInfo() = default;
+    virtual ~MidiDeviceInfo() = default;
+    MidiDeviceInfo(const MidiDeviceInfo& midiDeviceInfo) = default;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    int getType() const { return mType; }
+    int getUid() const { return mId; }
+    bool isPrivate() const { return mIsPrivate; }
+    const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
+    const Vector<String16>&  getOutputPortNames() const { return mOutputPortNames; }
+    String16 getProperty(const char* propertyName);
+
+    // The constants need to be kept in sync with MidiDeviceInfo.java
+    enum {
+        TYPE_USB = 1,
+        TYPE_VIRTUAL = 2,
+        TYPE_BLUETOOTH = 3,
+    };
+    static const char* const PROPERTY_NAME;
+    static const char* const PROPERTY_MANUFACTURER;
+    static const char* const PROPERTY_PRODUCT;
+    static const char* const PROPERTY_VERSION;
+    static const char* const PROPERTY_SERIAL_NUMBER;
+    static const char* const PROPERTY_ALSA_CARD;
+    static const char* const PROPERTY_ALSA_DEVICE;
+
+    friend bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs);
+    friend bool operator!=(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
+        return !(lhs == rhs);
+    }
+
+private:
+    status_t readStringVector(
+            const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength);
+    status_t writeStringVector(Parcel* parcel, const Vector<String16>& vector) const;
+
+    int32_t mType;
+    int32_t mId;
+    Vector<String16> mInputPortNames;
+    Vector<String16> mOutputPortNames;
+    os::PersistableBundle mProperties;
+    bool mIsPrivate;
+};
+
+}  // namespace midi
+}  // namespace media
+}  // namespace android
+
+#endif  // ANDROID_MEDIA_MIDI_DEVICE_INFO_H
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index 46f2815..35c4d42 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -26,7 +26,7 @@
 #include <core_jni_helpers.h>
 
 #include "android/media/midi/BpMidiDeviceServer.h"
-#include "media/MidiDeviceInfo.h"
+#include "MidiDeviceInfo.h"
 
 #include "include/amidi/AMidi.h"
 #include "amidi_internal.h"
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 680c879..f4f8d0b 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -26,7 +26,7 @@
 import java.util.Map;
 
 public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService {
-    private static final String TAG = "SampleMediaRoute2Serv";
+    private static final String TAG = "SampleMR2ProviderSvc";
 
     public static final String ROUTE_ID1 = "route_id1";
     public static final String ROUTE_NAME1 = "Sample Route 1";
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 7c1af4a..91297b0 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -110,3 +110,36 @@
     symbol_file: "libandroid_net.map.txt",
     unversioned: true,
 }
+
+
+// Aidl library for platform compat.
+cc_library_shared {
+    name: "lib-platform-compat-native-api",
+    cflags: [
+            "-Wall",
+            "-Werror",
+            "-Wno-missing-field-initializers",
+            "-Wno-unused-variable",
+            "-Wunused-parameter",
+        ],
+    shared_libs: [
+        "libbinder",
+         "libutils",
+    ],
+    aidl: {
+        local_include_dirs: ["aidl"],
+        export_aidl_headers: true,
+    },
+    srcs: [
+         ":platform-compat-native-aidl",
+    ],
+    export_include_dirs: ["aidl"],
+}
+
+filegroup {
+    name: "platform-compat-native-aidl",
+    srcs: [
+        "aidl/com/android/internal/compat/IPlatformCompatNative.aidl",
+    ],
+    path: "aidl",
+}
\ No newline at end of file
diff --git a/native/android/aidl/com/android/internal/compat/IPlatformCompatNative.aidl b/native/android/aidl/com/android/internal/compat/IPlatformCompatNative.aidl
new file mode 100644
index 0000000..347e4e8
--- /dev/null
+++ b/native/android/aidl/com/android/internal/compat/IPlatformCompatNative.aidl
@@ -0,0 +1,93 @@
+/*
+ * 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.internal.compat;
+
+/**
+ * Platform native private API for talking with the PlatformCompat service.
+ *
+ * <p> Should be used for gating and logging from non-app processes running cpp code.
+ * For app processes please use android.compat.Compatibility API.
+ *
+ * {@hide}
+ */
+interface IPlatformCompatNative
+{
+    /**
+     * Reports that a compatibility change is affecting an app process now.
+     *
+     * <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.
+     *
+     * @param changeId    The ID of the compatibility change taking effect.
+     * @param userId      The ID of the user that the operation is done for.
+     * @param packageName The package name of the app in question.
+     */
+     void reportChangeByPackageName(long changeId, @utf8InCpp String packageName, int userId);
+
+    /**
+     * 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.
+     *
+     * <p>Returns {@code true} if there is no installed package by the provided package name.
+     *
+     * <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, String)} would, so there is
+     * no need to call that method directly.
+     *
+     * @param changeId    The ID of the compatibility change in question.
+     * @param packageName The package name of the app in question.
+     * @param userId      The ID of the user that the operation is done for.
+     * @return {@code true} if the change is enabled for the current app.
+     */
+    boolean isChangeEnabledByPackageName(long changeId, @utf8InCpp String packageName, int userId);
+
+    /**
+     * 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> 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/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 53c0122..b34b31a 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -294,7 +294,7 @@
 
         auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats;
 
-        for (const auto& [surfaceControl, acquireTime, previousReleaseFence] : surfaceControlStats) {
+        for (const auto& [surfaceControl, acquireTime, previousReleaseFence, transformHint] : surfaceControlStats) {
             ASurfaceControl* aSurfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
             aSurfaceControlStats[aSurfaceControl].acquireTime = acquireTime;
             aSurfaceControlStats[aSurfaceControl].previousReleaseFence = previousReleaseFence;
diff --git a/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml
index 94f5b96..71e74cf 100644
--- a/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_left_navigation_bar.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
@@ -36,7 +36,7 @@
         android:background="@drawable/system_bar_background"
         android:animateLayoutChanges="true">
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/home"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -47,7 +47,7 @@
             android:paddingBottom="30dp"
         />
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/grid"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -59,7 +59,7 @@
             android:paddingBottom="30dp"
         />
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/hvac"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -110,4 +110,4 @@
 
     </LinearLayout>
 
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
index 708f595..f016dbf 100644
--- a/packages/CarSystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
+++ b/packages/CarSystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
@@ -36,7 +36,7 @@
         android:background="@drawable/system_bar_background"
         android:animateLayoutChanges="true">
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/home"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -47,7 +47,7 @@
             android:paddingBottom="30dp"
         />
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/hvac"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -59,4 +59,4 @@
             android:paddingBottom="30dp"
         />
     </LinearLayout>
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
index 18ae582..6c7a04f 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
@@ -33,7 +33,7 @@
         android:paddingEnd="20dp"
         android:gravity="center">
 
-        <com.android.systemui.statusbar.car.CarFacetButton
+        <com.android.systemui.navigationbar.car.CarFacetButton
             android:id="@+id/home"
             style="@style/NavigationBarButton"
             systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
@@ -48,7 +48,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <com.android.systemui.statusbar.car.CarFacetButton
+        <com.android.systemui.navigationbar.car.CarFacetButton
             android:id="@+id/maps_nav"
             style="@style/NavigationBarButton"
             systemui:categories="android.intent.category.APP_MAPS"
@@ -63,7 +63,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <com.android.systemui.statusbar.car.CarFacetButton
+        <com.android.systemui.navigationbar.car.CarFacetButton
             android:id="@+id/music_nav"
             style="@style/NavigationBarButton"
             systemui:categories="android.intent.category.APP_MUSIC"
@@ -79,7 +79,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <com.android.systemui.statusbar.car.CarFacetButton
+        <com.android.systemui.navigationbar.car.CarFacetButton
             android:id="@+id/phone_nav"
             style="@style/NavigationBarButton"
             systemui:icon="@drawable/car_ic_phone"
@@ -94,7 +94,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <com.android.systemui.statusbar.car.CarFacetButton
+        <com.android.systemui.navigationbar.car.CarFacetButton
             android:id="@+id/grid_nav"
             style="@style/NavigationBarButton"
             systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
@@ -109,7 +109,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/notifications"
             style="@style/NavigationBarButton"
             systemui:icon="@drawable/car_ic_notification"
@@ -123,7 +123,7 @@
             android:layout_height="match_parent"
             android:layout_weight="1"/>
 
-        <com.android.systemui.statusbar.car.AssitantButton
+        <com.android.systemui.navigationbar.car.AssitantButton
             android:id="@+id/assist"
             style="@style/NavigationBarButton"
             systemui:icon="@drawable/ic_mic_white"
@@ -144,4 +144,4 @@
 
     </LinearLayout>
 
-</com.android.systemui.statusbar.car.CarNavigationBarView>
\ No newline at end of file
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
index 28eba6c..0f964fd 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
@@ -31,14 +31,15 @@
         android:paddingStart="@*android:dimen/car_padding_5"
         android:paddingEnd="@*android:dimen/car_padding_5">
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarFacetButton
             android:id="@+id/home"
             android:layout_width="@*android:dimen/car_touch_target_size"
             android:layout_height="match_parent"
             android:background="?android:attr/selectableItemBackground"
-            android:src="@drawable/car_ic_overview"
+            systemui:icon="@drawable/car_ic_overview"
             systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
-        />
+            systemui:selectedIcon="@drawable/car_ic_overview_selected"
+            systemui:useMoreIcon="false"/>
     </LinearLayout>
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
 
diff --git a/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml
index d36d1d6..327610a 100644
--- a/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_right_navigation_bar.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
@@ -39,7 +39,7 @@
         android:background="@drawable/system_bar_background"
         android:animateLayoutChanges="true">
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/home"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -50,7 +50,7 @@
             android:paddingBottom="30dp"
         />
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/grid"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -62,7 +62,7 @@
             android:paddingBottom="30dp"
         />
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/hvac"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -113,4 +113,4 @@
 
     </LinearLayout>
 
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
index 708f595..f016dbf 100644
--- a/packages/CarSystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
+++ b/packages/CarSystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
@@ -36,7 +36,7 @@
         android:background="@drawable/system_bar_background"
         android:animateLayoutChanges="true">
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/home"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -47,7 +47,7 @@
             android:paddingBottom="30dp"
         />
 
-        <com.android.systemui.statusbar.car.CarNavigationButton
+        <com.android.systemui.navigationbar.car.CarNavigationButton
             android:id="@+id/hvac"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
@@ -59,4 +59,4 @@
             android:paddingBottom="30dp"
         />
     </LinearLayout>
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
index cae89c1..7299ddf 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/car_top_bar"
@@ -36,7 +36,7 @@
             android:layout_alignParentStart="true"
         >
 
-            <com.android.systemui.statusbar.car.CarNavigationButton
+            <com.android.systemui.navigationbar.car.CarNavigationButton
                 android:id="@+id/hvacleft"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -73,7 +73,7 @@
             android:layout_height="match_parent"
             android:layout_centerInParent="true"
         >
-            <com.android.systemui.statusbar.car.CarNavigationButton
+            <com.android.systemui.navigationbar.car.CarNavigationButton
                 android:id="@+id/qs"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -120,7 +120,7 @@
             android:layout_alignParentEnd="true"
         >
 
-            <com.android.systemui.statusbar.car.CarNavigationButton
+            <com.android.systemui.navigationbar.car.CarNavigationButton
                 android:id="@+id/hvacright"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
@@ -150,4 +150,4 @@
         </FrameLayout>
     </RelativeLayout>
 
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml
index 8247211..a71567c 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.statusbar.car.CarNavigationBarView
+<com.android.systemui.navigationbar.car.CarNavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/car_top_bar"
@@ -36,7 +36,7 @@
         android:layout_alignParentStart="true"
         >
 
-      <com.android.systemui.statusbar.car.CarNavigationButton
+      <com.android.systemui.navigationbar.car.CarNavigationButton
           android:id="@+id/hvacleft"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
@@ -70,7 +70,7 @@
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_centerInParent="true">
-      <com.android.systemui.statusbar.car.CarNavigationButton
+      <com.android.systemui.navigationbar.car.CarNavigationButton
           android:id="@+id/qs"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
@@ -114,7 +114,7 @@
         android:layout_alignParentEnd="true"
         >
 
-      <com.android.systemui.statusbar.car.CarNavigationButton
+      <com.android.systemui.navigationbar.car.CarNavigationButton
           android:id="@+id/hvacright"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
@@ -144,4 +144,4 @@
     </FrameLayout>
   </RelativeLayout>
 
-</com.android.systemui.statusbar.car.CarNavigationBarView>
+</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 467c4a4..fe042fe 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -40,4 +40,31 @@
          slots that may be reused for things like IME control. -->
     <integer name="config_maxNotificationIcons">0</integer>
 
+    <!-- SystemUI Services: The classes of the stuff to start. -->
+    <string-array name="config_systemUIServiceComponents" translatable="false">
+        <item>com.android.systemui.util.NotificationChannels</item>
+        <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
+        <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
+        <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.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>
+        <item>com.android.systemui.keyboard.KeyboardUI</item>
+        <item>com.android.systemui.pip.PipUI</item>
+        <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
+        <item>@string/config_systemUIVendorServiceComponent</item>
+        <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
+        <item>com.android.systemui.LatencyTester</item>
+        <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
+        <item>com.android.systemui.ScreenDecorations</item>
+        <item>com.android.systemui.biometrics.AuthController</item>
+        <item>com.android.systemui.SliceBroadcastRelayHandler</item>
+        <item>com.android.systemui.SizeCompatModeActivityController</item>
+        <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
+        <item>com.android.systemui.theme.ThemeOverlayController</item>
+        <item>com.android.systemui.navigationbar.car.CarNavigationBar</item>
+    </string-array>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
similarity index 65%
copy from packages/SystemUI/src/com/android/systemui/ComponentBinder.java
copy to packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 3b35c61..8e0a3eb 100644
--- a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -16,16 +16,19 @@
 
 package com.android.systemui;
 
+import com.android.systemui.navigationbar.car.CarNavigationBar;
+
 import dagger.Binds;
 import dagger.Module;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
 
-/**
- * Dagger Module that collects related sub-modules together.
- */
-@Module(includes = {ActivityBinder.class, ServiceBinder.class, SystemUIBinder.class})
-public abstract class ComponentBinder {
+/** Binder for car specific {@link SystemUI} modules. */
+@Module
+public abstract class CarSystemUIBinder {
     /** */
     @Binds
-    public abstract ContextComponentHelper bindComponentHelper(
-            ContextComponentResolver componentHelper);
+    @IntoMap
+    @ClassKey(CarNavigationBar.class)
+    public abstract SystemUI bindCarNavigationBar(CarNavigationBar sysui);
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
index be2d542..be4b889 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -20,7 +20,8 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.statusbar.car.CarFacetButtonController;
+import com.android.systemui.dagger.SystemUIRootComponent;
+import com.android.systemui.navigationbar.car.CarFacetButtonController;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 
@@ -41,7 +42,6 @@
                 .contextHolder(new ContextHolder(context))
                 .build();
         return DaggerCarSystemUIRootComponent.builder()
-                .dependencyProvider(new com.android.systemui.DependencyProvider())
                 .contextHolder(new ContextHolder(context))
                 .build();
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index b1067f8..93e553f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -23,6 +23,7 @@
 
 import com.android.systemui.car.CarNotificationEntryManager;
 import com.android.systemui.car.CarNotificationInterruptionStateProvider;
+import com.android.systemui.dagger.SystemUIRootComponent;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerImpl;
 import com.android.systemui.power.EnhancedEstimates;
@@ -101,6 +102,9 @@
             CarSystemUIRootComponent systemUIRootComponent);
 
     @Binds
+    public abstract StatusBar bindStatusBar(CarStatusBar statusBar);
+
+    @Binds
     @IntoMap
     @ClassKey(StatusBar.class)
     public abstract SystemUI providesStatusBar(CarStatusBar statusBar);
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
index 264b7d5..c2847c8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
@@ -16,6 +16,12 @@
 
 package com.android.systemui;
 
+import com.android.systemui.dagger.DependencyBinder;
+import com.android.systemui.dagger.DependencyProvider;
+import com.android.systemui.dagger.SystemServicesModule;
+import com.android.systemui.dagger.SystemUIModule;
+import com.android.systemui.dagger.SystemUIRootComponent;
+
 import javax.inject.Singleton;
 
 import dagger.Component;
@@ -26,8 +32,10 @@
                 DependencyProvider.class,
                 DependencyBinder.class,
                 SystemUIFactory.ContextHolder.class,
+                SystemServicesModule.class,
                 SystemUIModule.class,
-                CarSystemUIModule.class
+                CarSystemUIModule.class,
+                CarSystemUIBinder.class
         })
 interface CarSystemUIRootComponent extends SystemUIRootComponent {
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/AssitantButton.java
similarity index 93%
rename from packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java
rename to packages/CarSystemUI/src/com/android/systemui/navigationbar/car/AssitantButton.java
index b36a7da..c50de22 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/AssitantButton.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.car;
+package com.android.systemui.navigationbar.car;
 
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE;
 
@@ -33,6 +33,7 @@
 public class AssitantButton extends CarFacetButton {
 
     private static final String TAG = "CarFacetButton";
+    private final AssistUtils mAssistUtils;
     private IVoiceInteractionSessionShowCallback mShowCallback =
             new IVoiceInteractionSessionShowCallback.Stub() {
                 @Override
@@ -45,8 +46,6 @@
                     Log.d(TAG, "IVoiceInteractionSessionShowCallback onShown()");
                 }
             };
-    
-    private final AssistUtils mAssistUtils;
 
     public AssitantButton(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -63,7 +62,7 @@
     }
 
     @Override
-    protected void setupIntents(TypedArray typedArray){
+    protected void setupIntents(TypedArray typedArray) {
         // left blank because for the assistant button Intent will not be passed from the layout.
     }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButton.java
similarity index 98%
rename from packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
rename to packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButton.java
index 0421c3b..c46e6e7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButton.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.car;
+package com.android.systemui.navigationbar.car;
 
 import android.app.ActivityOptions;
 import android.content.Context;
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButtonController.java
similarity index 97%
rename from packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
rename to packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButtonController.java
index 5f99e17..30f63f0 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButtonController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.car;
+package com.android.systemui.navigationbar.car;
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
@@ -76,6 +76,7 @@
         }
     }
 
+    /** Removes all buttons from the button maps. */
     public void removeAll() {
         mButtonsByCategory.clear();
         mButtonsByPackage.clear();
@@ -129,7 +130,7 @@
 
         if (mSelectedFacetButtons != null) {
             Iterator<CarFacetButton> iterator = mSelectedFacetButtons.iterator();
-            while(iterator.hasNext()) {
+            while (iterator.hasNext()) {
                 CarFacetButton carFacetButton = iterator.next();
                 if (carFacetButton.getDisplayId() == validStackInfo.displayId) {
                     carFacetButton.setSelected(false);
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
new file mode 100644
index 0000000..63bc66a
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -0,0 +1,316 @@
+/*
+ * 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.systemui.navigationbar.car;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.inputmethodservice.InputMethodService;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.RegisterStatusBarResult;
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+
+import dagger.Lazy;
+
+/** Navigation bars customized for the automotive use case. */
+public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks {
+
+    private final CarNavigationBarController mCarNavigationBarController;
+    private final WindowManager mWindowManager;
+    private final DeviceProvisionedController mDeviceProvisionedController;
+    private final Lazy<FacetButtonTaskStackListener> mFacetButtonTaskStackListener;
+    private final Handler mMainHandler;
+    private final Lazy<KeyguardStateController> mKeyguardStateController;
+    private final Lazy<NavigationBarController> mNavigationBarController;
+
+    private IStatusBarService mBarService;
+    private CommandQueue mCommandQueue;
+    private ActivityManagerWrapper mActivityManagerWrapper;
+
+    // If the nav bar should be hidden when the soft keyboard is visible.
+    private boolean mHideNavBarForKeyboard;
+    private boolean mBottomNavBarVisible;
+
+    // Nav bar views.
+    private ViewGroup mNavigationBarWindow;
+    private ViewGroup mLeftNavigationBarWindow;
+    private ViewGroup mRightNavigationBarWindow;
+    private CarNavigationBarView mNavigationBarView;
+    private CarNavigationBarView mLeftNavigationBarView;
+    private CarNavigationBarView mRightNavigationBarView;
+
+    // To be attached to the navigation bars such that they can close the notification panel if
+    // it's open.
+    private boolean mDeviceIsSetUpForUser = true;
+
+    @Inject
+    public CarNavigationBar(Context context,
+            CarNavigationBarController carNavigationBarController,
+            WindowManager windowManager,
+            DeviceProvisionedController deviceProvisionedController,
+            Lazy<FacetButtonTaskStackListener> facetButtonTaskStackListener,
+            @MainHandler Handler mainHandler,
+            Lazy<KeyguardStateController> keyguardStateController,
+            Lazy<NavigationBarController> navigationBarController) {
+        super(context);
+        mCarNavigationBarController = carNavigationBarController;
+        mWindowManager = windowManager;
+        mDeviceProvisionedController = deviceProvisionedController;
+        mFacetButtonTaskStackListener = facetButtonTaskStackListener;
+        mMainHandler = mainHandler;
+        mKeyguardStateController = keyguardStateController;
+        mNavigationBarController = navigationBarController;
+    }
+
+    @Override
+    public void start() {
+        // Set initial state.
+        mHideNavBarForKeyboard = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
+        mBottomNavBarVisible = false;
+
+        // Get bar service.
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+
+        // Connect into the status bar manager service
+        mCommandQueue = getComponent(CommandQueue.class);
+        mCommandQueue.addCallback(this);
+
+        RegisterStatusBarResult result = null;
+        try {
+            result = mBarService.registerStatusBar(mCommandQueue);
+        } catch (RemoteException ex) {
+            ex.rethrowFromSystemServer();
+        }
+
+        mDeviceIsSetUpForUser = mDeviceProvisionedController.isCurrentUserSetup();
+        mDeviceProvisionedController.addCallback(
+                new DeviceProvisionedController.DeviceProvisionedListener() {
+                    @Override
+                    public void onUserSetupChanged() {
+                        mMainHandler.post(() -> restartNavBarsIfNecessary());
+                    }
+
+                    @Override
+                    public void onUserSwitched() {
+                        mMainHandler.post(() -> restartNavBarsIfNecessary());
+                    }
+                });
+
+        createNavigationBar(result);
+
+        mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
+        mActivityManagerWrapper.registerTaskStackListener(mFacetButtonTaskStackListener.get());
+
+        mCarNavigationBarController.connectToHvac();
+    }
+
+    private void restartNavBarsIfNecessary() {
+        boolean currentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
+        if (mDeviceIsSetUpForUser != currentUserSetup) {
+            mDeviceIsSetUpForUser = currentUserSetup;
+            restartNavBars();
+        }
+    }
+
+    /**
+     * Remove all content from navbars and rebuild them. Used to allow for different nav bars
+     * before and after the device is provisioned. . Also for change of density and font size.
+     */
+    private void restartNavBars() {
+        // remove and reattach all hvac components such that we don't keep a reference to unused
+        // ui elements
+        mCarNavigationBarController.removeAllFromHvac();
+
+        if (mNavigationBarWindow != null) {
+            mNavigationBarWindow.removeAllViews();
+            mNavigationBarView = null;
+        }
+
+        if (mLeftNavigationBarWindow != null) {
+            mLeftNavigationBarWindow.removeAllViews();
+            mLeftNavigationBarView = null;
+        }
+
+        if (mRightNavigationBarWindow != null) {
+            mRightNavigationBarWindow.removeAllViews();
+            mRightNavigationBarView = null;
+        }
+
+        buildNavBarContent();
+        // If the UI was rebuilt (day/night change) while the keyguard was up we need to
+        // correctly respect that state.
+        if (mKeyguardStateController.get().isShowing()) {
+            updateNavBarForKeyguardContent();
+        }
+    }
+
+    private void createNavigationBar(RegisterStatusBarResult result) {
+        buildNavBarWindows();
+        buildNavBarContent();
+        attachNavBarWindows();
+
+        // Try setting up the initial state of the nav bar if applicable.
+        if (result != null) {
+            setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken,
+                    result.mImeWindowVis, result.mImeBackDisposition,
+                    result.mShowImeSwitcher);
+        }
+
+        // There has been a car customized nav bar on the default display, so just create nav bars
+        // on external displays.
+        mNavigationBarController.get().createNavigationBars(/* includeDefaultDisplay= */ false,
+                result);
+    }
+
+    private void buildNavBarWindows() {
+        mNavigationBarWindow = mCarNavigationBarController.getBottomWindow();
+        mLeftNavigationBarWindow = mCarNavigationBarController.getLeftWindow();
+        mRightNavigationBarWindow = mCarNavigationBarController.getRightWindow();
+    }
+
+    private void buildNavBarContent() {
+        mNavigationBarView = mCarNavigationBarController.getBottomBar(mDeviceIsSetUpForUser);
+        if (mNavigationBarView != null) {
+            mNavigationBarWindow.addView(mNavigationBarView);
+        }
+
+        mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(mDeviceIsSetUpForUser);
+        if (mLeftNavigationBarView != null) {
+            mLeftNavigationBarWindow.addView(mLeftNavigationBarView);
+        }
+
+        mRightNavigationBarView = mCarNavigationBarController.getRightBar(mDeviceIsSetUpForUser);
+        if (mRightNavigationBarView != null) {
+            mRightNavigationBarWindow.addView(mRightNavigationBarView);
+        }
+    }
+
+    private void attachNavBarWindows() {
+        if (mNavigationBarWindow != null && !mBottomNavBarVisible) {
+            mBottomNavBarVisible = true;
+
+            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
+                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                    PixelFormat.TRANSLUCENT);
+            lp.setTitle("CarNavigationBar");
+            lp.windowAnimations = 0;
+            mWindowManager.addView(mNavigationBarWindow, lp);
+        }
+
+        if (mLeftNavigationBarWindow != null) {
+            int width = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.car_left_navigation_bar_width);
+            WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
+                    width, ViewGroup.LayoutParams.MATCH_PARENT,
+                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                    PixelFormat.TRANSLUCENT);
+            leftlp.setTitle("LeftCarNavigationBar");
+            leftlp.windowAnimations = 0;
+            leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+            leftlp.gravity = Gravity.LEFT;
+            mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
+        }
+        if (mRightNavigationBarWindow != null) {
+            int width = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.car_right_navigation_bar_width);
+            WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
+                    width, ViewGroup.LayoutParams.MATCH_PARENT,
+                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                    PixelFormat.TRANSLUCENT);
+            rightlp.setTitle("RightCarNavigationBar");
+            rightlp.windowAnimations = 0;
+            rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+            rightlp.gravity = Gravity.RIGHT;
+            mWindowManager.addView(mRightNavigationBarWindow, rightlp);
+        }
+    }
+
+    /**
+     * We register for soft keyboard visibility events such that we can hide the navigation bar
+     * giving more screen space to the IME. Note: this is optional and controlled by
+     * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}.
+     */
+    @Override
+    public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
+            boolean showImeSwitcher) {
+        if (!mHideNavBarForKeyboard) {
+            return;
+        }
+
+        if (mContext.getDisplay().getDisplayId() != displayId) {
+            return;
+        }
+
+        boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
+        mCarNavigationBarController.setBottomWindowVisibility(!isKeyboardVisible);
+    }
+
+    private void updateNavBarForKeyguardContent() {
+        if (mNavigationBarView != null) {
+            mNavigationBarView.showKeyguardButtons();
+        }
+        if (mLeftNavigationBarView != null) {
+            mLeftNavigationBarView.showKeyguardButtons();
+        }
+        if (mRightNavigationBarView != null) {
+            mRightNavigationBarView.showKeyguardButtons();
+        }
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print("  mTaskStackListener=");
+        pw.println(mFacetButtonTaskStackListener.get());
+        pw.print("  mNavigationBarView=");
+        pw.println(mNavigationBarView);
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
new file mode 100644
index 0000000..f59f886
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
@@ -0,0 +1,247 @@
+/*
+ * 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.systemui.navigationbar.car;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.car.hvac.HvacController;
+import com.android.systemui.statusbar.car.hvac.TemperatureView;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+/** A single class which controls the navigation bar views. */
+@Singleton
+public class CarNavigationBarController {
+
+    private final Context mContext;
+    private final NavigationBarViewFactory mNavigationBarViewFactory;
+    private final Lazy<HvacController> mHvacControllerLazy;
+
+    private boolean mShowBottom;
+    private boolean mShowLeft;
+    private boolean mShowRight;
+
+    private View.OnTouchListener mTopBarTouchListener;
+    private View.OnTouchListener mBottomBarTouchListener;
+    private View.OnTouchListener mLeftBarTouchListener;
+    private View.OnTouchListener mRightBarTouchListener;
+    private NotificationsShadeController mNotificationsShadeController;
+
+    private CarNavigationBarView mTopView;
+    private CarNavigationBarView mBottomView;
+    private CarNavigationBarView mLeftView;
+    private CarNavigationBarView mRightView;
+
+    @Inject
+    public CarNavigationBarController(Context context,
+            NavigationBarViewFactory navigationBarViewFactory,
+            Lazy<HvacController> hvacControllerLazy) {
+        mContext = context;
+        mNavigationBarViewFactory = navigationBarViewFactory;
+        mHvacControllerLazy = hvacControllerLazy;
+
+        // Read configuration.
+        mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
+        mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar);
+        mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar);
+    }
+
+    /** Connect to hvac service. */
+    public void connectToHvac() {
+        mHvacControllerLazy.get().connectToCarService();
+    }
+
+    /** Clean up hvac. */
+    public void removeAllFromHvac() {
+        mHvacControllerLazy.get().removeAllComponents();
+    }
+
+    /** Gets the bottom window if configured to do so. */
+    @Nullable
+    public ViewGroup getBottomWindow() {
+        return mShowBottom ? mNavigationBarViewFactory.getBottomWindow() : null;
+    }
+
+    /** Gets the left window if configured to do so. */
+    @Nullable
+    public ViewGroup getLeftWindow() {
+        return mShowLeft ? mNavigationBarViewFactory.getLeftWindow() : null;
+    }
+
+    /** Gets the right window if configured to do so. */
+    @Nullable
+    public ViewGroup getRightWindow() {
+        return mShowRight ? mNavigationBarViewFactory.getRightWindow() : null;
+    }
+
+    /** Toggles the bottom nav bar visibility. */
+    public boolean setBottomWindowVisibility(boolean isVisible) {
+        return setWindowVisibility(getBottomWindow(), isVisible);
+    }
+
+    /** Toggles the left nav bar visibility. */
+    public boolean setLeftWindowVisibility(boolean isVisible) {
+        return setWindowVisibility(getLeftWindow(), isVisible);
+    }
+
+    /** Toggles the right nav bar visibility. */
+    public boolean setRightWindowVisibility(boolean isVisible) {
+        return setWindowVisibility(getRightWindow(), isVisible);
+    }
+
+    private boolean setWindowVisibility(ViewGroup window, boolean isVisible) {
+        if (window == null) {
+            return false;
+        }
+
+        int newVisibility = isVisible ? View.VISIBLE : View.GONE;
+        if (window.getVisibility() == newVisibility) {
+            return false;
+        }
+
+        window.setVisibility(newVisibility);
+        return true;
+    }
+
+    /** Gets the top navigation bar with the appropriate listeners set. */
+    @NonNull
+    public CarNavigationBarView getTopBar(boolean isSetUp) {
+        mTopView = mNavigationBarViewFactory.getTopBar(isSetUp);
+        mTopView.setStatusBarWindowTouchListener(mTopBarTouchListener);
+        mTopView.setNotificationsPanelController(mNotificationsShadeController);
+        addTemperatureViewToController(mTopView);
+        return mTopView;
+    }
+
+    /** Gets the bottom navigation bar with the appropriate listeners set. */
+    @Nullable
+    public CarNavigationBarView getBottomBar(boolean isSetUp) {
+        if (!mShowBottom) {
+            return null;
+        }
+
+        mBottomView = mNavigationBarViewFactory.getBottomBar(isSetUp);
+        mBottomView.setStatusBarWindowTouchListener(mBottomBarTouchListener);
+        mBottomView.setNotificationsPanelController(mNotificationsShadeController);
+        addTemperatureViewToController(mBottomView);
+        return mBottomView;
+    }
+
+    /** Gets the left navigation bar with the appropriate listeners set. */
+    @Nullable
+    public CarNavigationBarView getLeftBar(boolean isSetUp) {
+        if (!mShowLeft) {
+            return null;
+        }
+
+        mLeftView = mNavigationBarViewFactory.getLeftBar(isSetUp);
+        mLeftView.setStatusBarWindowTouchListener(mLeftBarTouchListener);
+        mLeftView.setNotificationsPanelController(mNotificationsShadeController);
+        addTemperatureViewToController(mLeftView);
+        return mLeftView;
+    }
+
+    /** Gets the right navigation bar with the appropriate listeners set. */
+    @Nullable
+    public CarNavigationBarView getRightBar(boolean isSetUp) {
+        if (!mShowRight) {
+            return null;
+        }
+
+        mRightView = mNavigationBarViewFactory.getRightBar(isSetUp);
+        mRightView.setStatusBarWindowTouchListener(mRightBarTouchListener);
+        mRightView.setNotificationsPanelController(mNotificationsShadeController);
+        addTemperatureViewToController(mRightView);
+        return mRightView;
+    }
+
+    /** Sets a touch listener for the top navigation bar. */
+    public void registerTopBarTouchListener(View.OnTouchListener listener) {
+        mTopBarTouchListener = listener;
+        if (mTopView != null) {
+            mTopView.setStatusBarWindowTouchListener(mTopBarTouchListener);
+        }
+    }
+
+    /** Sets a touch listener for the bottom navigation bar. */
+    public void registerBottomBarTouchListener(View.OnTouchListener listener) {
+        mBottomBarTouchListener = listener;
+        if (mBottomView != null) {
+            mBottomView.setStatusBarWindowTouchListener(mBottomBarTouchListener);
+        }
+    }
+
+    /** Sets a touch listener for the left navigation bar. */
+    public void registerLeftBarTouchListener(View.OnTouchListener listener) {
+        mLeftBarTouchListener = listener;
+        if (mLeftView != null) {
+            mLeftView.setStatusBarWindowTouchListener(mLeftBarTouchListener);
+        }
+    }
+
+    /** Sets a touch listener for the right navigation bar. */
+    public void registerRightBarTouchListener(View.OnTouchListener listener) {
+        mRightBarTouchListener = listener;
+        if (mRightView != null) {
+            mRightView.setStatusBarWindowTouchListener(mRightBarTouchListener);
+        }
+    }
+
+    /** Sets a notification controller which toggles the notification panel. */
+    public void registerNotificationController(
+            NotificationsShadeController notificationsShadeController) {
+        mNotificationsShadeController = notificationsShadeController;
+        if (mTopView != null) {
+            mTopView.setNotificationsPanelController(mNotificationsShadeController);
+        }
+        if (mBottomView != null) {
+            mBottomView.setNotificationsPanelController(mNotificationsShadeController);
+        }
+        if (mLeftView != null) {
+            mLeftView.setNotificationsPanelController(mNotificationsShadeController);
+        }
+        if (mRightView != null) {
+            mRightView.setNotificationsPanelController(mNotificationsShadeController);
+        }
+    }
+
+    /** Interface for controlling the notifications shade. */
+    public interface NotificationsShadeController {
+        /** Toggles the visibility of the notifications shade. */
+        void togglePanel();
+    }
+
+    private void addTemperatureViewToController(View v) {
+        if (v instanceof TemperatureView) {
+            mHvacControllerLazy.get().addHvacTextView((TemperatureView) v);
+        } else if (v instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) v;
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                addTemperatureViewToController(viewGroup.getChildAt(i));
+            }
+        }
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
similarity index 86%
rename from packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
rename to packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
index 05a41e6..24f8b74 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.car;
+package com.android.systemui.navigationbar.car;
 
 import android.content.Context;
 import android.util.AttributeSet;
@@ -32,10 +32,10 @@
  * The navigation bar in the automotive use case is more like a list of shortcuts, rendered
  * in a linear layout.
  */
-class CarNavigationBarView extends LinearLayout {
+public class CarNavigationBarView extends LinearLayout {
     private View mNavButtons;
     private CarNavigationButton mNotificationsButton;
-    private CarStatusBar mCarStatusBar;
+    private CarNavigationBarController.NotificationsShadeController mNotificationsShadeController;
     private Context mContext;
     private View mLockScreenButtons;
     // used to wire in open/close gestures for notifications
@@ -81,8 +81,9 @@
         return super.onInterceptTouchEvent(ev);
     }
 
-    void setStatusBar(CarStatusBar carStatusBar) {
-        mCarStatusBar = carStatusBar;
+    public void setNotificationsPanelController(
+            CarNavigationBarController.NotificationsShadeController controller) {
+        mNotificationsShadeController = controller;
     }
 
     /**
@@ -90,7 +91,7 @@
      *
      * @param statusBarWindowTouchListener The listener to call from touch and intercept touch
      */
-    void setStatusBarWindowTouchListener(OnTouchListener statusBarWindowTouchListener) {
+    public void setStatusBarWindowTouchListener(OnTouchListener statusBarWindowTouchListener) {
         mStatusBarWindowTouchListener = statusBarWindowTouchListener;
     }
 
@@ -103,7 +104,9 @@
     }
 
     protected void onNotificationsClick(View v) {
-        mCarStatusBar.togglePanel();
+        if (mNotificationsShadeController != null) {
+            mNotificationsShadeController.togglePanel();
+        }
     }
 
     /**
@@ -134,7 +137,7 @@
      *
      * @param hasUnseen true if the unseen notification count is great than 0.
      */
-    void toggleNotificationUnseenIndicator(Boolean hasUnseen) {
+    public void toggleNotificationUnseenIndicator(Boolean hasUnseen) {
         if (mNotificationsButton == null) return;
 
         mNotificationsButton.setUnseen(hasUnseen);
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationButton.java
similarity index 97%
rename from packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
rename to packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationButton.java
index c0dcbbc..40823ab 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationButton.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.car;
+package com.android.systemui.navigationbar.car;
 
 import android.app.ActivityOptions;
 import android.content.Context;
@@ -85,6 +85,7 @@
         super.onFinishInflate();
         setScaleType(ImageView.ScaleType.CENTER);
         setAlpha(mUnselectedAlpha);
+        setImageResource(mIconResourceId);
         try {
             if (mIntent != null) {
                 final Intent intent = Intent.parseUri(mIntent, Intent.URI_INTENT_SCHEME);
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/FacetButtonTaskStackListener.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/FacetButtonTaskStackListener.java
new file mode 100644
index 0000000..4925220
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/FacetButtonTaskStackListener.java
@@ -0,0 +1,65 @@
+/*
+ * 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.systemui.navigationbar.car;
+
+import android.app.ActivityTaskManager;
+import android.util.Log;
+
+import com.android.systemui.shared.system.TaskStackChangeListener;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+/**
+ * An implementation of TaskStackChangeListener, that listens for changes in the system
+ * task stack and notifies the navigation bar.
+ */
+@Singleton
+class FacetButtonTaskStackListener extends TaskStackChangeListener {
+    private static final String TAG = FacetButtonTaskStackListener.class.getSimpleName();
+
+    private final Lazy<CarFacetButtonController> mFacetButtonControllerLazy;
+
+    @Inject
+    FacetButtonTaskStackListener(
+            Lazy<CarFacetButtonController> carFacetButtonControllerLazy) {
+        mFacetButtonControllerLazy = carFacetButtonControllerLazy;
+    }
+
+    @Override
+    public void onTaskStackChanged() {
+        try {
+            mFacetButtonControllerLazy.get().taskChanged(
+                    ActivityTaskManager.getService().getAllStackInfos());
+        } catch (Exception e) {
+            Log.e(TAG, "Getting StackInfo from activity manager failed", e);
+        }
+    }
+
+    @Override
+    public void onTaskDisplayChanged(int taskId, int newDisplayId) {
+        try {
+            mFacetButtonControllerLazy.get().taskChanged(
+                    ActivityTaskManager.getService().getAllStackInfos());
+        } catch (Exception e) {
+            Log.e(TAG, "Getting StackInfo from activity manager failed", e);
+        }
+
+    }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/NavigationBarViewFactory.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/NavigationBarViewFactory.java
new file mode 100644
index 0000000..519b33a2
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/NavigationBarViewFactory.java
@@ -0,0 +1,147 @@
+/*
+ * 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.systemui.navigationbar.car;
+
+import android.content.Context;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.LayoutRes;
+
+import com.android.systemui.R;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/** A factory that creates and caches views for navigation bars. */
+@Singleton
+public class NavigationBarViewFactory {
+
+    private static final String TAG = NavigationBarViewFactory.class.getSimpleName();
+    private static final ArrayMap<Type, Integer> sLayoutMap = setupLayoutMapping();
+
+    private static ArrayMap<Type, Integer> setupLayoutMapping() {
+        ArrayMap<Type, Integer> map = new ArrayMap<>();
+        map.put(Type.TOP, R.layout.car_top_navigation_bar);
+        map.put(Type.TOP_UNPROVISIONED, R.layout.car_top_navigation_bar_unprovisioned);
+        map.put(Type.BOTTOM, R.layout.car_navigation_bar);
+        map.put(Type.BOTTOM_UNPROVISIONED, R.layout.car_navigation_bar_unprovisioned);
+        map.put(Type.LEFT, R.layout.car_left_navigation_bar);
+        map.put(Type.LEFT_UNPROVISIONED, R.layout.car_left_navigation_bar_unprovisioned);
+        map.put(Type.RIGHT, R.layout.car_right_navigation_bar);
+        map.put(Type.RIGHT_UNPROVISIONED, R.layout.car_right_navigation_bar_unprovisioned);
+        return map;
+    }
+
+    private final Context mContext;
+    private final ArrayMap<Type, CarNavigationBarView> mCachedViewMap = new ArrayMap<>(
+            Type.values().length);
+    private final ArrayMap<Type, ViewGroup> mCachedContainerMap = new ArrayMap<>();
+
+    /** Type of navigation bar to be created. */
+    private enum Type {
+        TOP,
+        TOP_UNPROVISIONED,
+        BOTTOM,
+        BOTTOM_UNPROVISIONED,
+        LEFT,
+        LEFT_UNPROVISIONED,
+        RIGHT,
+        RIGHT_UNPROVISIONED
+    }
+
+    @Inject
+    public NavigationBarViewFactory(Context context) {
+        mContext = context;
+    }
+
+    /** Gets the bottom window. */
+    public ViewGroup getBottomWindow() {
+        return getWindowCached(Type.BOTTOM);
+    }
+
+    /** Gets the left window. */
+    public ViewGroup getLeftWindow() {
+        return getWindowCached(Type.LEFT);
+    }
+
+    /** Gets the right window. */
+    public ViewGroup getRightWindow() {
+        return getWindowCached(Type.RIGHT);
+    }
+
+    /** Gets the top bar. */
+    public CarNavigationBarView getTopBar(boolean isSetUp) {
+        return getBar(isSetUp, Type.TOP, Type.TOP_UNPROVISIONED);
+    }
+
+    /** Gets the bottom bar. */
+    public CarNavigationBarView getBottomBar(boolean isSetUp) {
+        return getBar(isSetUp, Type.BOTTOM, Type.BOTTOM_UNPROVISIONED);
+    }
+
+    /** Gets the left bar. */
+    public CarNavigationBarView getLeftBar(boolean isSetUp) {
+        return getBar(isSetUp, Type.LEFT, Type.LEFT_UNPROVISIONED);
+    }
+
+    /** Gets the right bar. */
+    public CarNavigationBarView getRightBar(boolean isSetUp) {
+        return getBar(isSetUp, Type.RIGHT, Type.RIGHT_UNPROVISIONED);
+    }
+
+    private ViewGroup getWindowCached(Type type) {
+        if (mCachedContainerMap.containsKey(type)) {
+            return mCachedContainerMap.get(type);
+        }
+
+        ViewGroup window = (ViewGroup) View.inflate(mContext,
+                R.layout.navigation_bar_window, /* root= */ null);
+        mCachedContainerMap.put(type, window);
+        return mCachedContainerMap.get(type);
+    }
+
+    private CarNavigationBarView getBar(boolean isSetUp, Type provisioned, Type unprovisioned) {
+        CarNavigationBarView view;
+        if (isSetUp) {
+            view = getBarCached(provisioned, sLayoutMap.get(provisioned));
+        } else {
+            view = getBarCached(unprovisioned, sLayoutMap.get(unprovisioned));
+        }
+
+        if (view == null) {
+            String name = isSetUp ? provisioned.name() : unprovisioned.name();
+            Log.e(TAG, "CarStatusBar failed inflate for " + name);
+            throw new RuntimeException(
+                    "Unable to build " + name + " nav bar due to missing layout");
+        }
+        return view;
+    }
+
+    private CarNavigationBarView getBarCached(Type type, @LayoutRes int barLayout) {
+        if (mCachedViewMap.containsKey(type)) {
+            return mCachedViewMap.get(type);
+        }
+
+        CarNavigationBarView view = (CarNavigationBarView) View.inflate(mContext, barLayout,
+                /* root= */ null);
+        mCachedViewMap.put(type, view);
+        return mCachedViewMap.get(type);
+    }
+}
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 90aba2f..aebb62d 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -23,7 +23,6 @@
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
 import android.car.Car;
 import android.car.drivingstate.CarDrivingStateEvent;
 import android.car.drivingstate.CarUxRestrictionsManager;
@@ -31,22 +30,16 @@
 import android.car.trust.CarTrustAgentEnrollmentManager;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.inputmethodservice.InputMethodService;
-import android.os.IBinder;
+import android.os.PowerManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import android.view.Display;
 import android.view.GestureDetector;
-import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.view.ViewTreeObserver;
-import android.view.WindowManager;
 
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
@@ -82,11 +75,13 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.navigationbar.car.CarFacetButtonController;
+import com.android.systemui.navigationbar.car.CarNavigationBarController;
+import com.android.systemui.navigationbar.car.CarNavigationBarView;
 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.FeatureFlags;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationListener;
@@ -98,11 +93,9 @@
 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.NewNotifPipeline;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -112,13 +105,18 @@
 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.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeScrimController;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
 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.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
@@ -140,8 +138,10 @@
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import dagger.Lazy;
+
 /**
- * A status bar (and navigation bar) tailored for the automotive use case.
+ * A status bar tailored for the automotive use case.
  */
 public class CarStatusBar extends StatusBar implements CarBatteryController.BatteryViewHandler {
     private static final String TAG = "CarStatusBar";
@@ -151,12 +151,11 @@
     private static final float FLING_ANIMATION_MAX_TIME = 0.5f;
     // acceleration rate for the fling animation
     private static final float FLING_SPEED_UP_FACTOR = 0.6f;
+    private final ScrimController mScrimController;
 
     private float mOpeningVelocity = DEFAULT_FLING_VELOCITY;
     private float mClosingVelocity = DEFAULT_FLING_VELOCITY;
 
-    private TaskStackListenerImpl mTaskStackListener;
-
     private FullscreenUserSwitcher mFullscreenUserSwitcher;
 
     private CarBatteryController mCarBatteryController;
@@ -173,14 +172,10 @@
     private CarNavigationBarView mRightNavigationBarView;
 
     private final Object mQueueLock = new Object();
-    private boolean mShowLeft;
-    private boolean mShowRight;
-    private boolean mShowBottom;
+    private final CarNavigationBarController mCarNavigationBarController;
     private CarFacetButtonController mCarFacetButtonController;
-    private ActivityManagerWrapper mActivityManagerWrapper;
     private DeviceProvisionedController mDeviceProvisionedController;
     private boolean mDeviceIsSetUpForUser = true;
-    private HvacController mHvacController;
     private DrivingStateHelper mDrivingStateHelper;
     private PowerManagerHelper mPowerManagerHelper;
     private FlingAnimationUtils mFlingAnimationUtils;
@@ -206,7 +201,6 @@
     // To be attached to the navigation bars such that they can close the notification panel if
     // it's open.
     private View.OnTouchListener mNavBarNotificationTouchListener;
-
     // Percentage from top of the screen after which the notification shade will open. This value
     // will be used while opening the notification shade.
     private int mSettleOpenPercentage;
@@ -217,23 +211,16 @@
     private int mPercentageFromBottom;
     // If notification shade is animation to close or to open.
     private boolean mIsNotificationAnimating;
-
     // Tracks when the notification shade is being scrolled. This refers to the glass pane being
     // scrolled not the recycler view.
     private boolean mIsTracking;
     private float mFirstTouchDownOnGlassPane;
-
     // If the notification card inside the recycler view is being swiped.
     private boolean mIsNotificationCardSwiping;
     // If notification shade is being swiped vertically to close.
     private boolean mIsSwipingVerticallyToClose;
     // Whether heads-up notifications should be shown when shade is open.
     private boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
-    // If the nav bar should be hidden when the soft keyboard is visible.
-    private boolean mHideNavBarForKeyboard;
-    private boolean mBottomNavBarVisible;
-
-    private final NavigationBarController mNavigationBarController;
 
     private final CarPowerStateListener mCarPowerStateListener =
             (int state) -> {
@@ -252,6 +239,7 @@
     @Inject
     public CarStatusBar(
             Context context,
+            FeatureFlags featureFlags,
             LightBarController lightBarController,
             AutoHideController autoHideController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -266,7 +254,7 @@
             DynamicPrivacyController dynamicPrivacyController,
             BypassHeadsUpNotifier bypassHeadsUpNotifier,
             @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
-            NotifPipelineInitializer notifPipelineInitializer,
+            Lazy<NewNotifPipeline> newNotifPipeline,
             FalsingManager falsingManager,
             BroadcastDispatcher broadcastDispatcher,
             RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -306,9 +294,19 @@
             StatusBarWindowController statusBarWindowController,
             StatusBarWindowViewController.Builder statusBarWindowViewControllerBuild,
             NotifLog notifLog,
-            DozeParameters dozeParameters) {
+            DozeParameters dozeParameters,
+            ScrimController scrimController,
+            Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+            DozeServiceHost dozeServiceHost,
+            PowerManager powerManager,
+            DozeScrimController dozeScrimController,
+
+            /* Car Settings injected components. */
+            CarNavigationBarController carNavigationBarController) {
         super(
                 context,
+                featureFlags,
                 lightBarController,
                 autoHideController,
                 keyguardUpdateMonitor,
@@ -323,7 +321,7 @@
                 dynamicPrivacyController,
                 bypassHeadsUpNotifier,
                 allowNotificationLongPress,
-                notifPipelineInitializer,
+                newNotifPipeline,
                 falsingManager,
                 broadcastDispatcher,
                 remoteInputQuickSettingsDisabler,
@@ -363,8 +361,15 @@
                 statusBarWindowController,
                 statusBarWindowViewControllerBuild,
                 notifLog,
-                dozeParameters);
-        mNavigationBarController = navigationBarController;
+                dozeParameters,
+                scrimController,
+                lockscreenWallpaperLazy,
+                biometricUnlockControllerLazy,
+                dozeServiceHost,
+                powerManager,
+                dozeScrimController);
+        mScrimController = scrimController;
+        mCarNavigationBarController = carNavigationBarController;
     }
 
     @Override
@@ -374,24 +379,12 @@
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mDeviceIsSetUpForUser = mDeviceProvisionedController.isCurrentUserSetup();
 
-        // Keyboard related setup, before nav bars are created.
-        mHideNavBarForKeyboard = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
-        mBottomNavBarVisible = false;
-
         // Need to initialize screen lifecycle before calling super.start - before switcher is
         // created.
         mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
         mScreenLifecycle.addObserver(mScreenObserver);
 
-        // Need to initialize HVAC controller before calling super.start - before system bars are
-        // created.
-        mHvacController = new HvacController(mContext);
-
         super.start();
-        mTaskStackListener = new TaskStackListenerImpl();
-        mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
-        mActivityManagerWrapper.registerTaskStackListener(mTaskStackListener);
 
         mNotificationPanel.setScrollingEnabled(true);
         mSettleOpenPercentage = mContext.getResources().getInteger(
@@ -404,8 +397,6 @@
         createBatteryController();
         mCarBatteryController.startListening();
 
-        mHvacController.connectToCarService();
-
         mDeviceProvisionedController.addCallback(
                 new DeviceProvisionedController.DeviceProvisionedListener() {
                     @Override
@@ -442,48 +433,24 @@
      * before and after the device is provisioned. . Also for change of density and font size.
      */
     private void restartNavBars() {
-        // remove and reattach all hvac components such that we don't keep a reference to unused
-        // ui elements
-        mHvacController.removeAllComponents();
         mCarFacetButtonController.removeAll();
 
         if (mNavigationBarWindow != null) {
-            mNavigationBarWindow.removeAllViews();
             mNavigationBarView = null;
         }
-
         if (mLeftNavigationBarWindow != null) {
-            mLeftNavigationBarWindow.removeAllViews();
             mLeftNavigationBarView = null;
         }
-
         if (mRightNavigationBarWindow != null) {
-            mRightNavigationBarWindow.removeAllViews();
             mRightNavigationBarView = null;
         }
 
         buildNavBarContent();
-        // If the UI was rebuilt (day/night change) while the keyguard was up we need to
-        // correctly respect that state.
-        if (mIsKeyguard) {
-            updateNavBarForKeyguardContent();
-        }
         // CarFacetButtonController was reset therefore we need to re-add the status bar elements
         // to the controller.
         mCarFacetButtonController.addAllFacetButtons(mStatusBarWindow);
     }
 
-    private void addTemperatureViewToController(View v) {
-        if (v instanceof TemperatureView) {
-            mHvacController.addHvacTextView((TemperatureView) v);
-        } else if (v instanceof ViewGroup) {
-            ViewGroup viewGroup = (ViewGroup) v;
-            for (int i = 0; i < viewGroup.getChildCount(); i++) {
-                addTemperatureViewToController(viewGroup.getChildAt(i));
-            }
-        }
-    }
-
     /**
      * Allows for showing or hiding just the navigation bars. This is indented to be used when
      * the full screen user selector is shown.
@@ -500,7 +467,6 @@
         }
     }
 
-
     @Override
     public boolean hideKeyguard() {
         boolean result = super.hideKeyguard();
@@ -905,205 +871,43 @@
 
     @Override
     protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
-        mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
-        mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar);
-        mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar);
-
         buildNavBarWindows();
         buildNavBarContent();
-        attachNavBarWindows();
-
-        // Try setting up the initial state of the nav bar if applicable.
-        if (result != null) {
-            setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken,
-                    result.mImeWindowVis, result.mImeBackDisposition,
-                    result.mShowImeSwitcher);
-        }
-
-        // There has been a car customized nav bar on the default display, so just create nav bars
-        // on external displays.
-        mNavigationBarController.createNavigationBars(false /* includeDefaultDisplay */, result);
     }
 
     private void buildNavBarContent() {
-        // Always build top bar.
-        buildTopBar((mDeviceIsSetUpForUser) ? R.layout.car_top_navigation_bar :
-                R.layout.car_top_navigation_bar_unprovisioned);
+        buildTopBar();
 
-        if (mShowBottom) {
-            buildBottomBar((mDeviceIsSetUpForUser) ? R.layout.car_navigation_bar :
-                    R.layout.car_navigation_bar_unprovisioned);
-        }
+        mNavigationBarView = mCarNavigationBarController.getBottomBar(mDeviceIsSetUpForUser);
+        mCarNavigationBarController.registerBottomBarTouchListener(
+                mNavBarNotificationTouchListener);
 
-        if (mShowLeft) {
-            buildLeft((mDeviceIsSetUpForUser) ? R.layout.car_left_navigation_bar :
-                    R.layout.car_left_navigation_bar_unprovisioned);
-        }
+        mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(mDeviceIsSetUpForUser);
+        mCarNavigationBarController.registerLeftBarTouchListener(
+                mNavBarNotificationTouchListener);
 
-        if (mShowRight) {
-            buildRight((mDeviceIsSetUpForUser) ? R.layout.car_right_navigation_bar :
-                    R.layout.car_right_navigation_bar_unprovisioned);
-        }
+        mRightNavigationBarView = mCarNavigationBarController.getLeftBar(mDeviceIsSetUpForUser);
+        mCarNavigationBarController.registerRightBarTouchListener(
+                mNavBarNotificationTouchListener);
+
+        mCarNavigationBarController.registerNotificationController(() -> togglePanel());
     }
 
     private void buildNavBarWindows() {
         mTopNavigationBarContainer = mStatusBarWindow
-            .findViewById(R.id.car_top_navigation_bar_container);
+                .findViewById(R.id.car_top_navigation_bar_container);
 
-        if (mShowBottom) {
-            mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
-                    R.layout.navigation_bar_window, null);
-        }
-        if (mShowLeft) {
-            mLeftNavigationBarWindow = (ViewGroup) View.inflate(mContext,
-                    R.layout.navigation_bar_window, null);
-        }
-        if (mShowRight) {
-            mRightNavigationBarWindow = (ViewGroup) View.inflate(mContext,
-                    R.layout.navigation_bar_window, null);
-        }
-
+        mNavigationBarWindow = mCarNavigationBarController.getBottomWindow();
+        mLeftNavigationBarWindow = mCarNavigationBarController.getLeftWindow();
+        mRightNavigationBarWindow = mCarNavigationBarController.getRightWindow();
     }
 
-    /**
-     * We register for soft keyboard visibility events such that we can hide the navigation bar
-     * giving more screen space to the IME. Note: this is optional and controlled by
-     * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}.
-     */
-    @Override
-    public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
-            boolean showImeSwitcher) {
-        if (!mHideNavBarForKeyboard) {
-            return;
-        }
-
-        if (mContext.getDisplay().getDisplayId() != displayId) {
-            return;
-        }
-
-        boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
-        showBottomNavBarWindow(isKeyboardVisible);
-    }
-
-    private void attachNavBarWindows() {
-        if (mShowBottom && !mBottomNavBarVisible) {
-            mBottomNavBarVisible = true;
-
-            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
-                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
-                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                    PixelFormat.TRANSLUCENT);
-            lp.setTitle("CarNavigationBar");
-            lp.windowAnimations = 0;
-            mWindowManager.addView(mNavigationBarWindow, lp);
-        }
-
-        if (mShowLeft) {
-            int width = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.car_left_navigation_bar_width);
-            WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
-                    width, LayoutParams.MATCH_PARENT,
-                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                    PixelFormat.TRANSLUCENT);
-            leftlp.setTitle("LeftCarNavigationBar");
-            leftlp.windowAnimations = 0;
-            leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
-            leftlp.gravity = Gravity.LEFT;
-            mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
-        }
-        if (mShowRight) {
-            int width = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.car_right_navigation_bar_width);
-            WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
-                    width, LayoutParams.MATCH_PARENT,
-                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                            | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
-                            | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                    PixelFormat.TRANSLUCENT);
-            rightlp.setTitle("RightCarNavigationBar");
-            rightlp.windowAnimations = 0;
-            rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
-            rightlp.gravity = Gravity.RIGHT;
-            mWindowManager.addView(mRightNavigationBarWindow, rightlp);
-        }
-    }
-
-    private void showBottomNavBarWindow(boolean isKeyboardVisible) {
-        if (!mShowBottom) {
-            return;
-        }
-
-        // If keyboard is visible and bottom nav bar not visible, this is the correct state, so do
-        // nothing. Same with if keyboard is not visible and bottom nav bar is visible.
-        if (isKeyboardVisible ^ mBottomNavBarVisible) {
-            return;
-        }
-
-        mNavigationBarWindow.setVisibility(isKeyboardVisible ? View.GONE : View.VISIBLE);
-        mBottomNavBarVisible = !isKeyboardVisible;
-    }
-
-    private void buildTopBar(int layout) {
+    private void buildTopBar() {
         mTopNavigationBarContainer.removeAllViews();
-        View.inflate(mContext, layout, mTopNavigationBarContainer);
-        mTopNavigationBarView = (CarNavigationBarView) mTopNavigationBarContainer.getChildAt(0);
-        if (mTopNavigationBarView == null) {
-            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_top_navigation_bar");
-            throw new RuntimeException("Unable to build top nav bar due to missing layout");
-        }
-        mTopNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mTopNavigationBarView);
-        mTopNavigationBarView.setStatusBarWindowTouchListener(mTopNavBarNotificationTouchListener);
-    }
-
-    private void buildBottomBar(int layout) {
-        // SystemUI requires that the navigation bar view have a parent. Since the regular
-        // StatusBar inflates navigation_bar_window as this parent view, use the same view for the
-        // CarNavigationBarView.
-        View.inflate(mContext, layout, mNavigationBarWindow);
-        mNavigationBarView = (CarNavigationBarView) mNavigationBarWindow.getChildAt(0);
-        if (mNavigationBarView == null) {
-            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
-            throw new RuntimeException("Unable to build bottom nav bar due to missing layout");
-        }
-        mNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mNavigationBarView);
-        mNavigationBarView.setStatusBarWindowTouchListener(mNavBarNotificationTouchListener);
-    }
-
-    private void buildLeft(int layout) {
-        View.inflate(mContext, layout, mLeftNavigationBarWindow);
-        mLeftNavigationBarView = (CarNavigationBarView) mLeftNavigationBarWindow.getChildAt(0);
-        if (mLeftNavigationBarView == null) {
-            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_left_navigation_bar");
-            throw new RuntimeException("Unable to build left nav bar due to missing layout");
-        }
-        mLeftNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mLeftNavigationBarView);
-        mLeftNavigationBarView.setStatusBarWindowTouchListener(mNavBarNotificationTouchListener);
-    }
-
-
-    private void buildRight(int layout) {
-        View.inflate(mContext, layout, mRightNavigationBarWindow);
-        mRightNavigationBarView = (CarNavigationBarView) mRightNavigationBarWindow.getChildAt(0);
-        if (mRightNavigationBarView == null) {
-            Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_right_navigation_bar");
-            throw new RuntimeException("Unable to build right nav bar due to missing layout");
-        }
-        mRightNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mRightNavigationBarView);
-        mRightNavigationBarView.setStatusBarWindowTouchListener(mNavBarNotificationTouchListener);
+        mTopNavigationBarView = mCarNavigationBarController.getTopBar(mDeviceIsSetUpForUser);
+        mCarNavigationBarController.registerTopBarTouchListener(
+                mTopNavBarNotificationTouchListener);
+        mTopNavigationBarContainer.addView(mTopNavigationBarView);
     }
 
     @Override
@@ -1117,8 +921,6 @@
                     + "," + mStackScroller.getScrollY());
         }
 
-        pw.print("  mTaskStackListener=");
-        pw.println(mTaskStackListener);
         pw.print("  mCarFacetButtonController=");
         pw.println(mCarFacetButtonController);
         pw.print("  mFullscreenUserSwitcher=");
@@ -1127,8 +929,6 @@
         pw.println(mCarBatteryController);
         pw.print("  mBatteryMeterView=");
         pw.println(mBatteryMeterView);
-        pw.print("  mNavigationBarView=");
-        pw.println(mNavigationBarView);
 
         if (Dependency.get(KeyguardUpdateMonitor.class) != null) {
             Dependency.get(KeyguardUpdateMonitor.class).dump(fd, pw, args);
@@ -1168,32 +968,6 @@
         }
     }
 
-    /**
-     * An implementation of TaskStackChangeListener, that listens for changes in the system
-     * task stack and notifies the navigation bar.
-     */
-    private class TaskStackListenerImpl extends TaskStackChangeListener {
-        @Override
-        public void onTaskStackChanged() {
-            try {
-                mCarFacetButtonController.taskChanged(
-                        ActivityTaskManager.getService().getAllStackInfos());
-            } catch (Exception e) {
-                Log.e(TAG, "Getting StackInfo from activity manager failed", e);
-            }
-        }
-
-        @Override
-        public void onTaskDisplayChanged(int taskId, int newDisplayId) {
-            try {
-                mCarFacetButtonController.taskChanged(
-                        ActivityTaskManager.getService().getAllStackInfos());
-            } catch (Exception e) {
-                Log.e(TAG, "Getting StackInfo from activity manager failed", e);
-            }
-        }
-    }
-
     private void onDrivingStateChanged(CarDrivingStateEvent notUsed) {
         // Check if we need to start the timer every time driving state changes.
         startSwitchToGuestTimerIfDrivingOnKeyguard();
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index f7e5d01..3b48259 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -18,7 +18,9 @@
 
 import static android.content.DialogInterface.BUTTON_NEGATIVE;
 import static android.content.DialogInterface.BUTTON_POSITIVE;
+import static android.os.UserManager.DISALLOW_ADD_USER;
 
+import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
@@ -54,7 +56,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * Displays a GridLayout with icons for the users in the system to allow switching between users.
@@ -80,7 +81,7 @@
         mCarUserManagerHelper = new CarUserManagerHelper(mContext);
         mUserManager = UserManager.get(mContext);
 
-        addItemDecoration(new ItemSpacingDecoration(context.getResources().getDimensionPixelSize(
+        addItemDecoration(new ItemSpacingDecoration(mContext.getResources().getDimensionPixelSize(
                 R.dimen.car_user_switcher_vertical_spacing_between_users)));
     }
 
@@ -108,21 +109,16 @@
      * @return the adapter
      */
     public void buildAdapter() {
-        List<UserRecord> userRecords = createUserRecords(getAllUsers());
+        List<UserRecord> userRecords = createUserRecords(getUsersForUserGrid());
         mAdapter = new UserAdapter(mContext, userRecords);
         super.setAdapter(mAdapter);
     }
 
-    private List<UserInfo> getAllUsers() {
-        Stream<UserInfo> userListStream =
-                mUserManager.getUsers(/* excludeDying= */ true).stream();
-
-        if (UserManager.isHeadlessSystemUserMode()) {
-            userListStream =
-                    userListStream.filter(userInfo -> userInfo.id != UserHandle.USER_SYSTEM);
-        }
-        userListStream = userListStream.filter(userInfo -> userInfo.supportsSwitchToByUser());
-        return userListStream.collect(Collectors.toList());
+    private List<UserInfo> getUsersForUserGrid() {
+        return mUserManager.getUsers(/* excludeDying= */ true)
+                .stream()
+                .filter(UserInfo::supportsSwitchToByUser)
+                .collect(Collectors.toList());
     }
 
     private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
@@ -140,8 +136,7 @@
                 continue;
             }
 
-            boolean isForeground =
-                    mCarUserManagerHelper.getCurrentForegroundUserId() == userInfo.id;
+            boolean isForeground = ActivityManager.getCurrentUser() == userInfo.id;
             UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */,
                     false /* isAddUser */, isForeground);
             userRecords.add(record);
@@ -151,7 +146,8 @@
         userRecords.add(createStartGuestUserRecord());
 
         // Add add user record if the foreground user can add users
-        if (mCarUserManagerHelper.canForegroundUserAddUsers()) {
+        UserHandle fgUserHandle = UserHandle.of(ActivityManager.getCurrentUser());
+        if (!mUserManager.hasUserRestriction(DISALLOW_ADD_USER, fgUserHandle)) {
             userRecords.add(createAddUserRecord());
         }
 
@@ -159,7 +155,7 @@
     }
 
     private UserRecord createForegroundUserRecord() {
-        return new UserRecord(mCarUserManagerHelper.getCurrentForegroundUserInfo(),
+        return new UserRecord(mUserManager.getUserInfo(ActivityManager.getCurrentUser()),
                 false /* isStartGuestSession */, false /* isAddUser */, true /* isForeground */);
     }
 
@@ -189,7 +185,7 @@
 
     private void onUsersUpdate() {
         mAdapter.clearUsers();
-        mAdapter.updateUsers(createUserRecords(getAllUsers()));
+        mAdapter.updateUsers(createUserRecords(getUsersForUserGrid()));
         mAdapter.notifyDataSetChanged();
     }
 
@@ -291,7 +287,7 @@
         }
 
         private void handleAddUserClicked() {
-            if (mCarUserManagerHelper.isUserLimitReached()) {
+            if (!mUserManager.canAddMoreUsers()) {
                 mAddUserView.setEnabled(true);
                 showMaxUserLimitReachedDialog();
             } else {
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
index 30429ed..e81be1b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -38,6 +38,8 @@
 import java.util.Map;
 import java.util.Objects;
 
+import javax.inject.Inject;
+
 /**
  * Manages the connection to the Car service and delegates value changes to the registered
  * {@link TemperatureView}s
@@ -119,6 +121,7 @@
         }
     };
 
+    @Inject
     public HvacController(Context context) {
         mContext = context;
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
index 820bea9..a5d3bf7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.car.privacy;
 
-import android.car.userlib.CarUserManagerHelper;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -38,10 +38,9 @@
     public PrivacyApplication(String packageName, Context context) {
         mPackageName = packageName;
         try {
-            CarUserManagerHelper carUserManagerHelper = new CarUserManagerHelper(context);
             ApplicationInfo app = context.getPackageManager()
                     .getApplicationInfoAsUser(packageName, 0,
-                            carUserManagerHelper.getCurrentForegroundUserId());
+                            ActivityManager.getCurrentUser());
             mIcon = context.getPackageManager().getApplicationIcon(app);
             mApplicationName = context.getPackageManager().getApplicationLabel(app).toString();
         } catch (PackageManager.NameNotFoundException e) {
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index d0a63f0..22c7c7a 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -143,6 +143,7 @@
     private boolean mHovering;
     private int mCurrentlyDisplayingGroupId;
     private boolean mShowing;
+    private boolean mDismissing;
     private boolean mExpanded;
     private View mExpandIcon;
     private final ServiceConnection mServiceConnection = new ServiceConnection() {
@@ -244,6 +245,7 @@
 
         mHovering = false;
         mShowing = false;
+        mDismissing = false;
         mExpanded = false;
         mWindow = mDialog.getWindow();
         mWindow.requestFeature(Window.FEATURE_NO_TITLE);
@@ -335,14 +337,11 @@
 
         mHandler.removeMessages(H.DISMISS);
         mHandler.removeMessages(H.SHOW);
-        if (!mShowing) {
+        if (!mShowing || mDismissing) {
             return;
         }
 
-        mListView.animate().cancel();
-
-        mListView.setTranslationY(0);
-        mListView.setAlpha(1);
+        mDismissing = true;
         mListView.animate()
                 .alpha(0)
                 .translationY(-mListView.getHeight())
@@ -354,7 +353,7 @@
                     }
                     mDialog.dismiss();
                     mShowing = false;
-                    mShowing = false;
+                    mDismissing = false;
                     // if mExpandIcon is null that means user never clicked on the expanded arrow
                     // which implies that the dialog is still not expanded. In that case we do
                     // not want to reset the state
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index aef6a3c..0d8e69b 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -10,4 +10,5 @@
 satk@google.com
 shuoq@google.com
 refuhoo@google.com
-nazaninb@google.com
\ No newline at end of file
+nazaninb@google.com
+sarahchin@google.com
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index cf286bd..738c425 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -99,11 +99,13 @@
             // init input stream before calling startInstallation(), which takes 90 seconds.
             initInputStream();
 
-            Thread thread = new Thread(() -> {
-                mInstallationSession =
-                        mDynSystem.startInstallation(mSystemSize, mUserdataSize);
-            });
-
+            Thread thread =
+                    new Thread(
+                            () -> {
+                                mDynSystem.startInstallation("userdata", mUserdataSize, false);
+                                mInstallationSession =
+                                        mDynSystem.startInstallation("system", mSystemSize, true);
+                            });
 
             thread.start();
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index c5138c5..1709506 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.content.Loader;
 import android.content.pm.ServiceInfo;
-import android.location.Criteria;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
@@ -265,11 +264,6 @@
             onLocationChanged(lastLocation);
         }
 
-        // Jumpstart location with a single forced update
-        Criteria oneTimeCriteria = new Criteria();
-        oneTimeCriteria.setAccuracy(Criteria.ACCURACY_FINE);
-        mLocationManager.requestSingleUpdate(oneTimeCriteria, this, Looper.getMainLooper());
-
         // The contract is that if we already have a valid,
         // result the we have to deliver it immediately.
         (new Handler(Looper.getMainLooper())).post(new Runnable() {
@@ -423,7 +417,7 @@
     }
 
     @Override
-    public void onLocationChanged(Location location) {
+    public void onLocationChanged(@Nullable Location location) {
         synchronized(mLocationLock) {
             // We expect the user to not move too fast while printing. Hence prefer more accurate
             // updates over more recent ones for LOCATION_UPDATE_MS. We add a 10% fudge factor here
diff --git a/packages/SettingsLib/SearchWidget/res/values-gl/strings.xml b/packages/SettingsLib/SearchWidget/res/values-gl/strings.xml
index e9e1ae8..856ee57 100644
--- a/packages/SettingsLib/SearchWidget/res/values-gl/strings.xml
+++ b/packages/SettingsLib/SearchWidget/res/values-gl/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="search_menu" msgid="1604061903696928905">"Buscar na configuración"</string>
+    <string name="search_menu" msgid="1604061903696928905">"Busca na configuración"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index bd1ed6a..b624df0 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -414,7 +414,7 @@
     <string name="disabled" msgid="9206776641295849915">"Desactivat"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"Amb permís"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"Sense permís"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"Instal·lar aplicacions desconegudes"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"Instal·la aplicacions desconegudes"</string>
     <string name="home" msgid="3256884684164448244">"Pàgina d\'inici de configuració"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index bab4cde..38ae9c2 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -311,7 +311,7 @@
     <string name="debug_layout" msgid="5981361776594526155">"Erakutsi diseinu-mugak"</string>
     <string name="debug_layout_summary" msgid="2001775315258637682">"Erakutsi kliparen mugak, marjinak, etab."</string>
     <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Behartu eskuin-ezker norabidea"</string>
-    <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Behartu pantaila-diseinuaren norabidea eskuin-ezker izatera eskualdeko ezarpen guztiekin"</string>
+    <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Behartu pantaila-diseinuaren norabidea eskuin-ezker izatera lurraldeko ezarpen guztiekin"</string>
     <string name="force_msaa" msgid="7920323238677284387">"Behartu 4x MSAA"</string>
     <string name="force_msaa_summary" msgid="9123553203895817537">"Gaitu 4x MSAA, OpenGL ES 2.0 aplikazioetan"</string>
     <string name="show_non_rect_clip" msgid="505954950474595172">"Araztu angeluzuzenak ez diren klip-eragiketak"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 2019caf..b89ea07 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -211,7 +211,7 @@
     <item msgid="1069584980746680398">"مقیاس پویانمایی 10 برابر"</item>
   </string-array>
   <string-array name="overlay_display_devices_entries">
-    <item msgid="1606809880904982133">"هیچ‌کدام"</item>
+    <item msgid="1606809880904982133">"خالی"</item>
     <item msgid="9033194758688161545">"480p"</item>
     <item msgid="1025306206556583600">"‏480p (ایمن)"</item>
     <item msgid="1853913333042744661">"720p"</item>
@@ -225,7 +225,7 @@
     <item msgid="1311305077526792901">"‏720p،‏ 1080p (صفحه‌نمایش دوتایی)"</item>
   </string-array>
   <string-array name="enable_opengl_traces_entries">
-    <item msgid="3191973083884253830">"هیچ‌کدام"</item>
+    <item msgid="3191973083884253830">"خالی"</item>
     <item msgid="9089630089455370183">"Logcat"</item>
     <item msgid="5397807424362304288">"‏Systrace (تصاویر گرافیکی)"</item>
     <item msgid="1340692776955662664">"‏فراخوانی پشته در glGetError"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 9d84090..a883d6cd 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -21,7 +21,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"اسکن شبکه‌ها امکان‌پذیر نیست"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"هیچ‌کدام"</string>
+    <string name="wifi_security_none" msgid="7985461072596594400">"خالی"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ذخیره‌شده"</string>
     <string name="wifi_disconnected" msgid="8085419869003922556">"اتصال قطع شد"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غیرفعال شد"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 61e1997..66c7a16 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -414,7 +414,7 @@
     <string name="disabled" msgid="9206776641295849915">"बंद किया गया"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"अनुमति है"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"अनुमति नहीं है"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"अनजान ऐप्लिकेशन इंस्टॉल करने का ऐक्सेस"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"अज्ञात ऐप्लिकेशन इंस्टॉल करने का ऐक्सेस"</string>
     <string name="home" msgid="3256884684164448244">"सेटिंग का होम पेज"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 45cd379..1388dbb 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -414,7 +414,7 @@
     <string name="disabled" msgid="9206776641295849915">"Letiltva"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"Engedélyezett"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"Nem engedélyezett"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"Új alkalmazások telepítése"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"Ismeretlen alkalmazások telepítése"</string>
     <string name="home" msgid="3256884684164448244">"Beállítások kezdőlapja"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 15b6da5..7ebe6b7 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -328,7 +328,7 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Batas proses background"</string>
     <string name="show_all_anrs" msgid="4924885492787069007">"Tampilkan ANR background"</string>
     <string name="show_all_anrs_summary" msgid="6636514318275139826">"Tampilkan dialog Aplikasi Tidak Merespons untuk aplikasi yang berjalan di background"</string>
-    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Tampilkan peringatan channel notifikasi"</string>
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Tampilkan peringatan saluran notifikasi"</string>
     <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Menampilkan peringatan di layar saat aplikasi memposting notifikasi tanpa channel yang valid"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Paksa izinkan aplikasi di eksternal"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string>
@@ -414,7 +414,7 @@
     <string name="disabled" msgid="9206776641295849915">"Dinonaktifkan"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"Diizinkan"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"Tidak diizinkan"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"Menginstal aplikasi yang tidak dikenal"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"Instal aplikasi tidak dikenal"</string>
     <string name="home" msgid="3256884684164448244">"Layar Utama Setelan"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 3fe9855..253104b 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -414,7 +414,7 @@
     <string name="disabled" msgid="9206776641295849915">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"ಅನುಮತಿಸಲಾಗಿದೆ"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"ಅಪರಿಚಿತ ಆಪ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"ಅಪರಿಚಿತ ಆ್ಯಪ್‍‍ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ"</string>
     <string name="home" msgid="3256884684164448244">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಮುಖಪುಟ"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 72b2159..dd1ff30 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -101,7 +101,7 @@
     <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Файл өткөрүү серверине туташкан жок"</string>
     <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Киргизүү түзмөгүнө туташты"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="6436258151814414028">"Интернетке мүмкүнчүлүк алуу үчүн түзмөккө туташты"</string>
-    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1322694224800769308">"Жергиликтүү Интернет туташуусу түзмөк менен бөлүшүлүүдө"</string>
+    <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1322694224800769308">"Түзмөк модем катары иштөөдө"</string>
     <string name="bluetooth_pan_profile_summary_use_for" msgid="5736111170225304239">"Интернетке туташуу үчүн колдонулсун"</string>
     <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"MAP үчүн колдонуу"</string>
     <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"SIM картаны пайдалануу үчүн колдонуу"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 3e3768a..6e1d29a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -414,7 +414,7 @@
     <string name="disabled" msgid="9206776641295849915">"Отключено"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"Разрешено"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"Запрещено"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"Установка неизвестных приложений"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"Неизвестные приложения"</string>
     <string name="home" msgid="3256884684164448244">"Настройки"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0 %"</item>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index a05797e..006fc9f 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -175,7 +175,7 @@
     <item msgid="1744840221860799971">"Yamezimwa"</item>
     <item msgid="3054662377365844197">"Zote"</item>
     <item msgid="688870735111627832">"Zote isipokuwa redio"</item>
-    <item msgid="2850427388488887328">"keneli pekee"</item>
+    <item msgid="2850427388488887328">"kiini pekee"</item>
   </string-array>
   <string-array name="select_logpersist_summaries">
     <item msgid="2216470072500521830">"Imezimwa"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 3591670..03ae94f 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -414,7 +414,7 @@
     <string name="disabled" msgid="9206776641295849915">"నిలిపివేయబడింది"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"అనుమతించినవి"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"అనుమతించబడలేదు"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"తెలియని యాప్‌లను ఇన్‌స్టాల్ చేయడం"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"తెలియని యాప్‌ల ఇన్‌స్టలేషన్"</string>
     <string name="home" msgid="3256884684164448244">"సెట్టింగ్‌ల హోమ్"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 1f923af..a855741 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -127,6 +127,9 @@
     <!-- Summary for Connected wifi network without internet -->
     <string name="wifi_connected_no_internet">Connected, no internet</string>
 
+    <!-- Summary for connected network without internet due to private dns validation failed [CHAR LIMIT=NONE] -->
+    <string name="private_dns_broken">Private DNS server cannot be accessed</string>
+
     <!-- Summary for connected wifi network with partial internet connectivity [CHAR LIMIT=50] -->
     <string name="wifi_limited_connection">Limited connection</string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
index a18600a..2b84196 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
@@ -48,11 +48,21 @@
         return getEnabledServicesFromSettings(context, UserHandle.myUserId());
     }
 
+    /**
+     * Check if the accessibility service is crashed
+     *
+     * @param packageName The package name to check
+     * @param serviceName The service name to check
+     * @param installedServiceInfos The list of installed accessibility service
+     * @return {@code true} if the accessibility service is crashed for the user.
+     * {@code false} otherwise.
+     */
     public static boolean hasServiceCrashed(String packageName, String serviceName,
-            List<AccessibilityServiceInfo> enabledServiceInfos) {
-        for (int i = 0; i < enabledServiceInfos.size(); i++) {
-            AccessibilityServiceInfo accessibilityServiceInfo = enabledServiceInfos.get(i);
-            final ServiceInfo serviceInfo = enabledServiceInfos.get(i).getResolveInfo().serviceInfo;
+            List<AccessibilityServiceInfo> installedServiceInfos) {
+        for (int i = 0; i < installedServiceInfos.size(); i++) {
+            final AccessibilityServiceInfo accessibilityServiceInfo = installedServiceInfos.get(i);
+            final ServiceInfo serviceInfo =
+                    installedServiceInfos.get(i).getResolveInfo().serviceInfo;
             if (TextUtils.equals(serviceInfo.packageName, packageName)
                     && TextUtils.equals(serviceInfo.name, serviceName)) {
                 return accessibilityServiceInfo.crashed;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 81d1ea5..16fd51f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -50,6 +50,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
@@ -1568,7 +1569,13 @@
                         NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
                     return context.getString(R.string.wifi_limited_connection);
                 } else if (!nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
-                    return context.getString(R.string.wifi_connected_no_internet);
+                    final String mode = Settings.Global.getString(context.getContentResolver(),
+                            Settings.Global.PRIVATE_DNS_MODE);
+                    if (nc.isPrivateDnsBroken()) {
+                        return context.getString(R.string.private_dns_broken);
+                    } else {
+                        return context.getString(R.string.wifi_connected_no_internet);
+                    }
                 }
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 5352936..b11585a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -31,6 +31,7 @@
 import android.net.wifi.WifiSsid;
 import android.os.Handler;
 import android.os.Looper;
+import android.provider.Settings;
 
 import com.android.settingslib.R;
 
@@ -163,7 +164,13 @@
                 statusLabel = mContext.getString(R.string.wifi_limited_connection);
                 return;
             } else if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
-                statusLabel = mContext.getString(R.string.wifi_status_no_internet);
+                final String mode = Settings.Global.getString(mContext.getContentResolver(),
+                        Settings.Global.PRIVATE_DNS_MODE);
+                if (networkCapabilities.isPrivateDnsBroken()) {
+                    statusLabel = mContext.getString(R.string.private_dns_broken);
+                } else {
+                    statusLabel = mContext.getString(R.string.wifi_status_no_internet);
+                }
                 return;
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
index 4e6c005..658a0b5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
@@ -93,6 +93,7 @@
             if (bssid != null) {
                 visibility.append(" ").append(bssid);
             }
+            visibility.append(" technology = ").append(info.getWifiTechnology());
             visibility.append(" rssi=").append(info.getRssi());
             visibility.append(" ");
             visibility.append(" score=").append(info.score);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
index 5d2a0d1d..e936c35 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
@@ -8,6 +8,7 @@
 
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.OpFeatureEntry;
 import android.app.AppOpsManager.PackageOps;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -17,6 +18,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -161,7 +163,10 @@
         accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_BACKGROUND,
             AppOpsManager.OP_FLAG_SELF), time);
 
-        return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes, null /*durations*/,
-            null /*rejectTimes*/, null /* proxyUids */, null /* proxyPackages */);
+        OpFeatureEntry.Builder featureEntry = new OpFeatureEntry.Builder(false, accessTimes,
+                null /*rejectTimes*/, null /*durations*/, null /* proxyUids */,
+                null /* proxyPackages */, null /* proxyFeatureIds */);
+        return new OpEntry(op, AppOpsManager.MODE_ALLOWED,
+                new Pair[]{new Pair(null, featureEntry)});
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 7a553fc..3fde48b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -7,6 +7,7 @@
 
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.OpFeatureEntry;
 import android.app.AppOpsManager.PackageOps;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -17,6 +18,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -162,7 +164,11 @@
         final LongSparseLongArray durations = new LongSparseLongArray();
         durations.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
                 AppOpsManager.OP_FLAG_SELF), duration);
-        return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes,
-                null /*rejectTimes*/, durations, null /* proxyUids */, null /* proxyPackages */);
+
+        OpFeatureEntry.Builder featureEntry = new OpFeatureEntry.Builder(false, accessTimes,
+                null /*rejectTimes*/, durations, null /* proxyUids */,
+                null /* proxyPackages */, null /* proxyFeatureIds */);
+        return new OpEntry(op, AppOpsManager.MODE_ALLOWED,
+                new Pair[]{new Pair(null, featureEntry)});
     }
 }
diff --git a/packages/SettingsProvider/OWNERS b/packages/SettingsProvider/OWNERS
new file mode 100644
index 0000000..2054129
--- /dev/null
+++ b/packages/SettingsProvider/OWNERS
@@ -0,0 +1,3 @@
+hackbod@google.com
+svetoslavganov@google.com
+moltmann@google.com
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 8c97057..146f30d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -152,6 +152,8 @@
         Settings.Secure.SILENCE_TIMER_TOUCH_COUNT,
         Settings.Secure.DARK_MODE_DIALOG_SEEN,
         Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED,
-        Settings.Secure.AWARE_LOCK_ENABLED
+        Settings.Secure.AWARE_LOCK_ENABLED,
+        Settings.Secure.AWARE_TAP_PAUSE_GESTURE_COUNT,
+        Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index ef67bbd..f7fc0c5 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -220,6 +220,8 @@
         VALIDATORS.put(Secure.SILENCE_ALARMS_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.SILENCE_TIMER_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.SILENCE_CALL_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.AWARE_TAP_PAUSE_GESTURE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.AWARE_TAP_PAUSE_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.ODI_CAPTIONS_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.UI_NIGHT_MODE, new InclusiveIntegerRangeValidator(0, 2));
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 17c621e..44de09b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1497,21 +1497,7 @@
         }
 
         if (upgradeVersion == 94) {
-            // Add wireless charging started sound setting
-            if (mUserHandle == UserHandle.USER_SYSTEM) {
-                db.beginTransaction();
-                SQLiteStatement stmt = null;
-                try {
-                    stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
-                            + " VALUES(?,?);");
-                    loadStringSetting(stmt, Settings.Global.CHARGING_STARTED_SOUND,
-                            R.string.def_wireless_charging_started_sound);
-                    db.setTransactionSuccessful();
-                } finally {
-                    db.endTransaction();
-                    if (stmt != null) stmt.close();
-                }
-            }
+            // charging sound moved to SettingsProvider version 184
             upgradeVersion = 95;
         }
 
@@ -2562,8 +2548,6 @@
                     R.string.def_car_dock_sound);
             loadStringSetting(stmt, Settings.Global.CAR_UNDOCK_SOUND,
                     R.string.def_car_undock_sound);
-            loadStringSetting(stmt, Settings.Global.CHARGING_STARTED_SOUND,
-                    R.string.def_wireless_charging_started_sound);
 
             loadIntegerSetting(stmt, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED,
                     R.integer.def_dock_audio_media_enabled);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 2ce4e97..e24d387 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1347,6 +1347,9 @@
         dumpSetting(s, p,
                 Settings.Global.CHARGING_STARTED_SOUND,
                 GlobalSettingsProto.Sounds.CHARGING_STARTED);
+        dumpSetting(s, p,
+                Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+                GlobalSettingsProto.Sounds.WIRELESS_CHARGING_STARTED);
         p.end(soundsToken);
 
         final long soundTriggerToken = p.start(GlobalSettingsProto.SOUND_TRIGGER);
@@ -2047,6 +2050,12 @@
         dumpSetting(s, p,
                 Settings.Secure.SKIP_TOUCH_COUNT,
                 SecureSettingsProto.Gesture.SKIP_TOUCH_COUNT);
+        dumpSetting(s, p,
+                Settings.Secure.AWARE_TAP_PAUSE_GESTURE_COUNT,
+                SecureSettingsProto.Gesture.AWARE_TAP_PAUSE_GESTURE_COUNT);
+        dumpSetting(s, p,
+                Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT,
+                SecureSettingsProto.Gesture.AWARE_TAP_PAUSE_TOUCH_COUNT);
         p.end(gestureToken);
 
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a9c466e..80faf476 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -56,6 +56,7 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IUserRestrictionsListener;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
@@ -65,7 +66,6 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.UserManagerInternal;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.provider.Settings.Global;
@@ -84,7 +84,6 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
 import com.android.providers.settings.SettingsState.Setting;
-import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 
 import com.google.android.collect.Sets;
@@ -286,8 +285,6 @@
     // We have to call in the user manager with no lock held,
     private volatile UserManager mUserManager;
 
-    private UserManagerInternal mUserManagerInternal;
-
     // We have to call in the package manager with no lock held,
     private volatile IPackageManager mPackageManager;
 
@@ -317,7 +314,6 @@
 
         synchronized (mLock) {
             mUserManager = UserManager.get(getContext());
-            mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
             mPackageManager = AppGlobals.getPackageManager();
             mHandlerThread = new HandlerThread(LOG_TAG,
                     Process.THREAD_PRIORITY_BACKGROUND);
@@ -902,95 +898,100 @@
         // TODO: The current design of settings looking different based on user restrictions
         // should be reworked to keep them separate and system code should check the setting
         // first followed by checking the user restriction before performing an operation.
-        UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
-        userManager.addUserRestrictionsListener((int userId, Bundle newRestrictions,
-                Bundle prevRestrictions) -> {
-            Set<String> changedRestrictions = getRestrictionDiff(prevRestrictions, newRestrictions);
-            // We are changing the settings affected by restrictions to their current
-            // value with a forced update to ensure that all cross profile dependencies
-            // are taken into account. Also make sure the settings update to.. the same
-            // value passes the security checks, so clear binder calling id.
-            if (changedRestrictions.contains(UserManager.DISALLOW_SHARE_LOCATION)) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    synchronized (mLock) {
-                        Setting setting = getSecureSetting(
-                                Settings.Secure.LOCATION_MODE, userId);
-                        updateSecureSetting(Settings.Secure.LOCATION_MODE,
-                                setting != null ? setting.getValue() : null, null,
-                                true, userId, true);
-                        setting = getSecureSetting(
-                                Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
-                        updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
-                                setting != null ? setting.getValue() : null, null,
-                                true, userId, true);
+        IUserRestrictionsListener listener = new IUserRestrictionsListener.Stub() {
+            @Override
+            public void onUserRestrictionsChanged(int userId,
+                    Bundle newRestrictions, Bundle prevRestrictions) {
+                Set<String> changedRestrictions =
+                        getRestrictionDiff(prevRestrictions, newRestrictions);
+                // We are changing the settings affected by restrictions to their current
+                // value with a forced update to ensure that all cross profile dependencies
+                // are taken into account. Also make sure the settings update to.. the same
+                // value passes the security checks, so clear binder calling id.
+                if (changedRestrictions.contains(UserManager.DISALLOW_SHARE_LOCATION)) {
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        synchronized (mLock) {
+                            Setting setting = getSecureSetting(
+                                    Settings.Secure.LOCATION_MODE, userId);
+                            updateSecureSetting(Settings.Secure.LOCATION_MODE,
+                                    setting != null ? setting.getValue() : null, null,
+                                            true, userId, true);
+                            setting = getSecureSetting(
+                                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userId);
+                            updateSecureSetting(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+                                    setting != null ? setting.getValue() : null, null,
+                                            true, userId, true);
+                        }
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
                     }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
+                }
+                if (changedRestrictions.contains(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
+                        || changedRestrictions.contains(
+                                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)) {
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        synchronized (mLock) {
+                            Setting setting = getGlobalSetting(
+                                    Settings.Global.INSTALL_NON_MARKET_APPS);
+                            String value = setting != null ? setting.getValue() : null;
+                            updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS,
+                                    value, null, true, userId, true);
+                        }
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
+                }
+                if (changedRestrictions.contains(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        synchronized (mLock) {
+                            Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED);
+                            String value = setting != null ? setting.getValue() : null;
+                            updateGlobalSetting(Settings.Global.ADB_ENABLED,
+                                    value, null, true, userId, true);
+                        }
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
+                }
+                if (changedRestrictions.contains(UserManager.ENSURE_VERIFY_APPS)) {
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        synchronized (mLock) {
+                            Setting enable = getGlobalSetting(
+                                    Settings.Global.PACKAGE_VERIFIER_ENABLE);
+                            String enableValue = enable != null ? enable.getValue() : null;
+                            updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
+                                    enableValue, null, true, userId, true);
+                            Setting include = getGlobalSetting(
+                                    Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
+                            String includeValue = include != null ? include.getValue() : null;
+                            updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
+                                    includeValue, null, true, userId, true);
+                        }
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
+                }
+                if (changedRestrictions.contains(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        synchronized (mLock) {
+                            Setting setting = getGlobalSetting(
+                                    Settings.Global.PREFERRED_NETWORK_MODE);
+                            String value = setting != null ? setting.getValue() : null;
+                            updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE,
+                                    value, null, true, userId, true);
+                        }
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
                 }
             }
-            if (changedRestrictions.contains(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
-                    || changedRestrictions.contains(
-                            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    synchronized (mLock) {
-                        Setting setting = getGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS);
-                        String value = setting != null ? setting.getValue() : null;
-                        updateGlobalSetting(Settings.Global.INSTALL_NON_MARKET_APPS,
-                                value, null, true, userId, true);
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-            if (changedRestrictions.contains(UserManager.DISALLOW_DEBUGGING_FEATURES)) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    synchronized (mLock) {
-                        Setting setting = getGlobalSetting(Settings.Global.ADB_ENABLED);
-                        String value = setting != null ? setting.getValue() : null;
-                        updateGlobalSetting(Settings.Global.ADB_ENABLED,
-                                value, null, true, userId, true);
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-            if (changedRestrictions.contains(UserManager.ENSURE_VERIFY_APPS)) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    synchronized (mLock) {
-                        Setting enable = getGlobalSetting(
-                                Settings.Global.PACKAGE_VERIFIER_ENABLE);
-                        String enableValue = enable != null ? enable.getValue() : null;
-                        updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_ENABLE,
-                                enableValue, null, true, userId, true);
-                        Setting include = getGlobalSetting(
-                                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB);
-                        String includeValue = include != null ? include.getValue() : null;
-                        updateGlobalSetting(Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
-                                includeValue, null, true, userId, true);
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-            if (changedRestrictions.contains(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    synchronized (mLock) {
-                        Setting setting = getGlobalSetting(
-                                Settings.Global.PREFERRED_NETWORK_MODE);
-                        String value = setting != null ? setting.getValue() : null;
-                        updateGlobalSetting(Settings.Global.PREFERRED_NETWORK_MODE,
-                                value, null, true, userId, true);
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-        });
+        };
+        mUserManager.addUserRestrictionsListener(listener);
     }
 
     private static Set<String> getRestrictionDiff(Bundle prevRestrictions, Bundle newRestrictions) {
@@ -1185,6 +1186,17 @@
                 MUTATION_OPERATION_RESET, false, mode);
     }
 
+    private boolean isSettingRestrictedForUser(String name, int userId,
+            String value, int callerUid) {
+        final long oldId = Binder.clearCallingIdentity();
+        try {
+            return (name != null
+                    && mUserManager.isSettingRestrictedForUser(name, userId, value, callerUid));
+        } finally {
+            Binder.restoreCallingIdentity(oldId);
+        }
+    }
+
     private boolean mutateGlobalSetting(String name, String value, String tag,
             boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
             int mode) {
@@ -1196,8 +1208,7 @@
 
         // If this is a setting that is currently restricted for this user, do not allow
         // unrestricting changes.
-        if (name != null && mUserManagerInternal.isSettingRestrictedForUser(
-                name, callingUserId, value, Binder.getCallingUid())) {
+        if (isSettingRestrictedForUser(name, callingUserId, value, Binder.getCallingUid())) {
             return false;
         }
 
@@ -1505,8 +1516,7 @@
 
         // If this is a setting that is currently restricted for this user, do not allow
         // unrestricting changes.
-        if (name != null && mUserManagerInternal.isSettingRestrictedForUser(
-                name, callingUserId, value, Binder.getCallingUid())) {
+        if (isSettingRestrictedForUser(name, callingUserId, value, Binder.getCallingUid())) {
             return false;
         }
 
@@ -1646,8 +1656,7 @@
         // Resolve the userId on whose behalf the call is made.
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
 
-        if (name != null && mUserManagerInternal.isSettingRestrictedForUser(
-                name, callingUserId, value, Binder.getCallingUid())) {
+        if (isSettingRestrictedForUser(name, callingUserId, value, Binder.getCallingUid())) {
             return false;
         }
 
@@ -3184,7 +3193,7 @@
                         } catch (SecurityException e) {
                             Slog.w(LOG_TAG, "Failed to notify for " + userId + ": " + uri, e);
                         }
-                        if (DEBUG || true) {
+                        if (DEBUG) {
                             Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
                         }
                     } break;
@@ -3197,7 +3206,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 183;
+            private static final int SETTINGS_VERSION = 184;
 
             private final int mUserId;
 
@@ -3836,23 +3845,7 @@
                 }
 
                 if (currentVersion == 155) {
-                    // Version 156: Set the default value for CHARGING_STARTED_SOUND.
-                    final SettingsState globalSettings = getGlobalSettingsLocked();
-                    final String oldValue = globalSettings.getSettingLocked(
-                            Global.CHARGING_STARTED_SOUND).getValue();
-                    final String oldDefault = getContext().getResources().getString(
-                            R.string.def_wireless_charging_started_sound);
-                    if (TextUtils.equals(null, oldValue)
-                            || TextUtils.equals(oldValue, oldDefault)) {
-                        final String defaultValue = getContext().getResources().getString(
-                                R.string.def_charging_started_sound);
-                        if (!TextUtils.isEmpty(defaultValue)) {
-                            globalSettings.insertSettingLocked(
-                                    Settings.Global.CHARGING_STARTED_SOUND, defaultValue,
-                                    null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                        }
-
-                    }
+                    // Version 156: migrated to version 184
                     currentVersion = 156;
                 }
 
@@ -4407,6 +4400,48 @@
                     currentVersion = 183;
                 }
 
+                if (currentVersion == 183) {
+                    // Version 184: Set default values for WIRELESS_CHARGING_STARTED_SOUND
+                    // and CHARGING_STARTED_SOUND
+                    final SettingsState globalSettings = getGlobalSettingsLocked();
+
+                    final String oldValueWireless = globalSettings.getSettingLocked(
+                            Global.WIRELESS_CHARGING_STARTED_SOUND).getValue();
+                    final String oldValueWired = globalSettings.getSettingLocked(
+                            Global.CHARGING_STARTED_SOUND).getValue();
+
+                    final String defaultValueWireless = getContext().getResources().getString(
+                            R.string.def_wireless_charging_started_sound);
+                    final String defaultValueWired = getContext().getResources().getString(
+                            R.string.def_charging_started_sound);
+
+                    // wireless charging sound
+                    if (oldValueWireless == null
+                            || TextUtils.equals(oldValueWireless, defaultValueWired)) {
+                        if (!TextUtils.isEmpty(defaultValueWireless)) {
+                            globalSettings.insertSettingLocked(
+                                    Global.WIRELESS_CHARGING_STARTED_SOUND, defaultValueWireless,
+                                    null /* tag */, true /* makeDefault */,
+                                    SettingsState.SYSTEM_PACKAGE_NAME);
+                        } else if (!TextUtils.isEmpty(defaultValueWired)) {
+                            // if the wireless sound is empty, use the wired charging sound
+                            globalSettings.insertSettingLocked(
+                                    Global.WIRELESS_CHARGING_STARTED_SOUND, defaultValueWired,
+                                    null /* tag */, true /* makeDefault */,
+                                    SettingsState.SYSTEM_PACKAGE_NAME);
+                        }
+                    }
+
+                    // wired charging sound
+                    if (oldValueWired == null && !TextUtils.isEmpty(defaultValueWired)) {
+                        globalSettings.insertSettingLocked(
+                                Global.CHARGING_STARTED_SOUND, defaultValueWired,
+                                null /* tag */, true /* makeDefault */,
+                                SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+                    currentVersion = 184;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 62827bc..179ba8a 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -559,6 +559,7 @@
                     Settings.Global.WIFI_WATCHDOG_ON,
                     Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON,
                     Settings.Global.CHARGING_STARTED_SOUND,
+                    Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
                     Settings.Global.WINDOW_ANIMATION_SCALE,
                     Settings.Global.WTF_IS_FATAL,
                     Settings.Global.ZEN_MODE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index e11c063..54e291f 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -247,23 +247,6 @@
             android:exported="false" />
 
         <receiver
-            android:name=".BugreportReceiver"
-            android:permission="android.permission.DUMP">
-            <intent-filter>
-                <action android:name="com.android.internal.intent.action.BUGREPORT_STARTED" />
-                <action android:name="com.android.internal.intent.action.BUGREPORT_FINISHED" />
-            </intent-filter>
-        </receiver>
-
-        <receiver
-            android:name=".RemoteBugreportReceiver"
-            android:permission="android.permission.DUMP">
-            <intent-filter>
-                <action android:name="com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED" />
-            </intent-filter>
-        </receiver>
-
-        <receiver
             android:name=".BugreportRequestedReceiver"
             android:permission="android.permission.TRIGGER_SHELL_BUGREPORT">
             <intent-filter>
diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml
index d0373b1..394f852 100644
--- a/packages/Shell/res/values-pt-rBR/strings.xml
+++ b/packages/Shell/res/values-pt-rBR/strings.xml
@@ -18,21 +18,21 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_notification_channel" msgid="2574150205913861141">"Relatórios de bugs"</string>
-    <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
+    <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório de bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório de bug <xliff:g id="ID">#%d</xliff:g> capturado"</string>
-    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório de bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"O relatório de bugs será exibido no smartphone em breve"</string>
-    <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Selecione para compartilhar o relatório do bug"</string>
-    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Selecione para compartilhar seu relatório do bug sem uma captura de tela ou aguarde a conclusão"</string>
+    <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Selecione para compartilhar o relatório de bug"</string>
+    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório de bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Selecione para compartilhar seu relatório de bug sem uma captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"Os relatórios de bugs contêm dados dos diversos arquivos de registros do sistema, que podem incluir dados que você considera confidenciais (como dados de uso de apps e de local). Compartilhe relatórios de bugs somente com pessoas e apps nos quais você confia."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Não mostrar novamente"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Não foi possível ler o arquivo de relatório de bug"</string>
-    <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Não foi possível adicionar detalhes do relatório do bug ao arquivo ZIP"</string>
+    <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Não foi possível adicionar detalhes do relatório de bug ao arquivo ZIP"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"sem nome"</string>
     <string name="bugreport_info_action" msgid="2158204228510576227">"Detalhes"</string>
     <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Capturas de tela"</string>
@@ -43,5 +43,5 @@
     <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
     <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
     <string name="save" msgid="4781509040564835759">"Salvar"</string>
-    <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Compartilhar relatório do bug"</string>
+    <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Compartilhar relatório de bug"</string>
 </resources>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index d0373b1..394f852 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -18,21 +18,21 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_notification_channel" msgid="2574150205913861141">"Relatórios de bugs"</string>
-    <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
+    <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório de bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório de bug <xliff:g id="ID">#%d</xliff:g> capturado"</string>
-    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório de bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"O relatório de bugs será exibido no smartphone em breve"</string>
-    <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Selecione para compartilhar o relatório do bug"</string>
-    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Selecione para compartilhar seu relatório do bug sem uma captura de tela ou aguarde a conclusão"</string>
+    <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Selecione para compartilhar o relatório de bug"</string>
+    <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório de bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Selecione para compartilhar seu relatório de bug sem uma captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"Os relatórios de bugs contêm dados dos diversos arquivos de registros do sistema, que podem incluir dados que você considera confidenciais (como dados de uso de apps e de local). Compartilhe relatórios de bugs somente com pessoas e apps nos quais você confia."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Não mostrar novamente"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Não foi possível ler o arquivo de relatório de bug"</string>
-    <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Não foi possível adicionar detalhes do relatório do bug ao arquivo ZIP"</string>
+    <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Não foi possível adicionar detalhes do relatório de bug ao arquivo ZIP"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"sem nome"</string>
     <string name="bugreport_info_action" msgid="2158204228510576227">"Detalhes"</string>
     <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Capturas de tela"</string>
@@ -43,5 +43,5 @@
     <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
     <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
     <string name="save" msgid="4781509040564835759">"Salvar"</string>
-    <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Compartilhar relatório do bug"</string>
+    <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Compartilhar relatório de bug"</string>
 </resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 665bde3..1b35770 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -56,16 +56,11 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.IBinder.DeathRecipient;
-import android.os.IDumpstate;
-import android.os.IDumpstateListener;
-import android.os.IDumpstateToken;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -80,7 +75,6 @@
 import android.view.ContextThemeWrapper;
 import android.view.IWindowManager;
 import android.view.View;
-import android.view.View.OnFocusChangeListener;
 import android.view.WindowManager;
 import android.widget.Button;
 import android.widget.EditText;
@@ -122,31 +116,9 @@
 import java.util.zip.ZipOutputStream;
 
 /**
- * Service used to keep progress of bugreport processes ({@code dumpstate} and
- * {@code BugreportManager}).
+ * Service used to trigger system bugreports.
  * <p>
- * There can be 2 workflows. One workflow via ({@code dumpstate}) is:
- * <ol>
- * <li>When {@code dumpstate} starts, it sends a {@code BUGREPORT_STARTED} with a sequential id,
- * its pid, and the estimated total effort.
- * <li>{@link BugreportReceiver} receives the intent and delegates it to this service.
- * <li>Upon start, this service:
- * <ol>
- * <li>Issues a system notification so user can watch the progress (which is 0% initially).
- * <li>Polls the {@link SystemProperties} for updates on the {@code dumpstate} progress.
- * <li>If the progress changed, it updates the system notification.
- * </ol>
- * <li>As {@code dumpstate} progresses, it updates the system property.
- * <li>When {@code dumpstate} finishes, it sends a {@code BUGREPORT_FINISHED} intent.
- * <li>{@link BugreportReceiver} receives the intent and delegates it to this service, which in
- * turn:
- * <ol>
- * <li>Updates the system notification so user can share the bugreport.
- * <li>Stops monitoring that {@code dumpstate} process.
- * <li>Stops itself if it doesn't have any process left to monitor.
- * </ol>
- * </ol>
- * The second workflow using Bugreport API({@code BugreportManager}) is:
+ * The workflow uses Bugreport API({@code BugreportManager}) and is as follows:
  * <ol>
  * <li>System apps like Settings or SysUI broadcasts {@code BUGREPORT_REQUESTED}.
  * <li>{@link BugreportRequestedReceiver} receives the intent and delegates it to this service.
@@ -164,18 +136,14 @@
 
     private static final String AUTHORITY = "com.android.shell";
 
-    // External intents sent by dumpstate.
-    static final String INTENT_BUGREPORT_STARTED =
-            "com.android.internal.intent.action.BUGREPORT_STARTED";
-    static final String INTENT_BUGREPORT_FINISHED =
-            "com.android.internal.intent.action.BUGREPORT_FINISHED";
-    static final String INTENT_REMOTE_BUGREPORT_FINISHED =
-            "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
-
     // External intent used to trigger bugreport API.
     static final String INTENT_BUGREPORT_REQUESTED =
             "com.android.internal.intent.action.BUGREPORT_REQUESTED";
 
+    // Intent sent to notify external apps that bugreport finished
+    static final String INTENT_BUGREPORT_FINISHED =
+            "com.android.internal.intent.action.BUGREPORT_FINISHED";
+
     // Internal intents used on notification actions.
     static final String INTENT_BUGREPORT_CANCEL = "android.intent.action.BUGREPORT_CANCEL";
     static final String INTENT_BUGREPORT_SHARE = "android.intent.action.BUGREPORT_SHARE";
@@ -188,7 +156,6 @@
     static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE";
     static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
     static final String EXTRA_ID = "android.intent.extra.ID";
-    static final String EXTRA_PID = "android.intent.extra.PID";
     static final String EXTRA_MAX = "android.intent.extra.MAX";
     static final String EXTRA_NAME = "android.intent.extra.NAME";
     static final String EXTRA_TITLE = "android.intent.extra.TITLE";
@@ -218,15 +185,9 @@
      */
     static final int SCREENSHOT_DELAY_SECONDS = 3;
 
-    // TODO: will be gone once fully migrated to Binder
-    /** System properties used to communicate with dumpstate progress. */
-    private static final String DUMPSTATE_PREFIX = "dumpstate.";
-    private static final String NAME_SUFFIX = ".name";
+    /** System property where dumpstate stores last triggered bugreport id */
     private static final String PROPERTY_LAST_ID = "dumpstate.last_id";
 
-    /** System property (and value) used to stop dumpstate. */
-    // TODO: should call ActiveManager API instead
-    private static final String CTL_STOP = "ctl.stop";
     private static final String BUGREPORT_SERVICE = "bugreport";
 
     /**
@@ -273,8 +234,6 @@
 
     private File mScreenshotsDir;
 
-    private boolean mUsingBugreportApi;
-
     private BugreportManager mBugreportManager;
 
     /**
@@ -452,9 +411,9 @@
                 cleanupOldFiles(MIN_KEEP_COUNT, MIN_KEEP_AGE);
                 final Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
                 intent.putExtra(EXTRA_BUGREPORT, bugreportFilePath);
-                addScreenshotToIntent(intent, mInfo);
+                intent.putExtra(EXTRA_SCREENSHOT, getScreenshotForIntent(mInfo));
                 mContext.sendBroadcast(intent, android.Manifest.permission.DUMP);
-                onBugreportFinished(mInfo.id);
+                onBugreportFinished(mInfo);
             }
         }
     }
@@ -475,14 +434,17 @@
                 android.Manifest.permission.DUMP);
     }
 
-    private static void addScreenshotToIntent(Intent intent, BugreportInfo info) {
-        final File screenshotFile = info.screenshotFiles.isEmpty()
-                ? null : info.screenshotFiles.get(0);
-        if (screenshotFile != null && screenshotFile.length() > 0) {
+    /**
+     * Checks if screenshot array is non-empty and returns the first screenshot's path. The first
+     * screenshot is the default screenshot for the bugreport types that take it.
+     */
+    private static String getScreenshotForIntent(BugreportInfo info) {
+        if (!info.screenshotFiles.isEmpty()) {
+            final File screenshotFile = info.screenshotFiles.get(0);
             final String screenshotFilePath = screenshotFile.getAbsolutePath();
-            intent.putExtra(EXTRA_SCREENSHOT, screenshotFilePath);
+            return screenshotFilePath;
         }
-        return;
+        return null;
     }
 
     private static String generateFileHash(String fileName) {
@@ -558,40 +520,24 @@
             Log.v(TAG, "handleMessage(): " + dumpIntent((Intent) parcel));
             final Intent intent;
             if (parcel instanceof Intent) {
-                // The real intent was passed to BugreportReceiver, which delegated to the service.
+                // The real intent was passed to BugreportRequestedReceiver,
+                // which delegated to the service.
                 intent = (Intent) parcel;
             } else {
                 intent = (Intent) msg.obj;
             }
             final String action = intent.getAction();
-            final int pid = intent.getIntExtra(EXTRA_PID, 0);
             final int id = intent.getIntExtra(EXTRA_ID, 0);
             final int max = intent.getIntExtra(EXTRA_MAX, -1);
             final String name = intent.getStringExtra(EXTRA_NAME);
 
             if (DEBUG)
-                Log.v(TAG, "action: " + action + ", name: " + name + ", id: " + id + ", pid: "
-                        + pid + ", max: " + max);
+                Log.v(TAG, "action: " + action + ", name: " + name + ", id: " + id
+                        + ", max: " + max);
             switch (action) {
                 case INTENT_BUGREPORT_REQUESTED:
                     startBugreportAPI(intent);
                     break;
-                case INTENT_BUGREPORT_STARTED:
-                    if (!mUsingBugreportApi && !startProgress(name, id, pid, max)) {
-                        stopSelfWhenDone();
-                        return;
-                    }
-                    break;
-                case INTENT_BUGREPORT_FINISHED:
-                    if (!mUsingBugreportApi) {
-                        if (id == 0) {
-                            // Shouldn't happen, unless BUGREPORT_FINISHED is received
-                            // from a legacy, out-of-sync dumpstate process.
-                            Log.w(TAG, "Missing " + EXTRA_ID + " on intent " + intent);
-                        }
-                        onBugreportFinished(id, intent);
-                    }
-                    break;
                 case INTENT_BUGREPORT_INFO_LAUNCH:
                     launchBugreportInfoDialog(id);
                     break;
@@ -633,52 +579,12 @@
     private BugreportInfo getInfo(int id) {
         final BugreportInfo bugreportInfo = mBugreportInfos.get(id);
         if (bugreportInfo == null) {
-            Log.w(TAG, "Not monitoring process with ID " + id);
+            Log.w(TAG, "Not monitoring bugreports with ID " + id);
             return null;
         }
         return bugreportInfo;
     }
 
-    /**
-     * Creates the {@link BugreportInfo} for a process and issue a system notification to
-     * indicate its progress.
-     *
-     * @return whether it succeeded or not.
-     */
-    private boolean startProgress(String name, int id, int pid, int max) {
-        if (name == null) {
-            Log.w(TAG, "Missing " + EXTRA_NAME + " on start intent");
-        }
-        if (id == -1) {
-            Log.e(TAG, "Missing " + EXTRA_ID + " on start intent");
-            return false;
-        }
-        if (pid == -1) {
-            Log.e(TAG, "Missing " + EXTRA_PID + " on start intent");
-            return false;
-        }
-        if (max <= 0) {
-            Log.e(TAG, "Invalid value for extra " + EXTRA_MAX + ": " + max);
-            return false;
-        }
-
-        final BugreportInfo info = new BugreportInfo(mContext, id, pid, name, max);
-        if (mBugreportInfos.indexOfKey(id) >= 0) {
-            // BUGREPORT_STARTED intent was already received; ignore it.
-            Log.w(TAG, "ID " + id + " already watched");
-            return true;
-        }
-        final DumpstateListener listener = new DumpstateListener(info);
-        mBugreportInfos.put(info.id, info);
-        if (listener.connect()) {
-            updateProgress(info);
-            return true;
-        } else {
-            Log.w(TAG, "not updating progress because it could not connect to dumpstate");
-            return false;
-        }
-    }
-
     private String getBugreportBaseName(@BugreportParams.BugreportMode int type) {
         String buildId = SystemProperties.get("ro.build.id", "UNKNOWN_BUILD");
         String deviceName = SystemProperties.get("ro.product.name", "UNKNOWN_DEVICE");
@@ -694,7 +600,6 @@
     }
 
     private void startBugreportAPI(Intent intent) {
-        mUsingBugreportApi = true;
         String shareTitle = intent.getStringExtra(EXTRA_TITLE);
         String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION);
         int bugreportType = intent.getIntExtra(EXTRA_BUGREPORT_TYPE,
@@ -702,10 +607,8 @@
         String baseName = getBugreportBaseName(bugreportType);
         String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
 
-        // pid not used in this workflow, so setting default = 0
-        BugreportInfo info = new BugreportInfo(mContext, 0 /* pid */, baseName, name,
-                100 /* max progress*/, shareTitle, shareDescription, bugreportType,
-                mUsingBugreportApi);
+        BugreportInfo info = new BugreportInfo(mContext, baseName, name,
+                100 /* max progress*/, shareTitle, shareDescription, bugreportType);
 
         ParcelFileDescriptor bugreportFd = info.createBugreportFd();
         if (bugreportFd == null) {
@@ -885,11 +788,7 @@
         final BugreportInfo info = getInfo(id);
         if (info != null && !info.finished) {
             Log.i(TAG, "Cancelling bugreport service (ID=" + id + ") on user's request");
-            if (mUsingBugreportApi) {
-                mBugreportManager.cancelBugreport();
-            } else {
-                setSystemProperty(CTL_STOP, BUGREPORT_SERVICE);
-            }
+            mBugreportManager.cancelBugreport();
             deleteScreenshots(info);
         }
         synchronized (mLock) {
@@ -1087,94 +986,15 @@
     }
 
     /**
-     * Handles the BUGREPORT_FINISHED intent sent by {@code dumpstate}.
-     */
-    private void onBugreportFinished(int id, Intent intent) {
-        final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
-        if (bugreportFile == null) {
-            // Should never happen, dumpstate always set the file.
-            Log.wtf(TAG, "Missing " + EXTRA_BUGREPORT + " on intent " + intent);
-            return;
-        }
-        final int max = intent.getIntExtra(EXTRA_MAX, -1);
-        final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
-        final String shareTitle = intent.getStringExtra(EXTRA_TITLE);
-        final String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION);
-        onBugreportFinished(id, bugreportFile, screenshotFile, shareTitle, shareDescription, max);
-    }
-
-    /**
-     * Handles the onfinish() call by BugreportCallbackImpl using the id
-     */
-    private void onBugreportFinished(int id) {
-        BugreportInfo info = getInfo(id);
-        final File bugreportFile = info.bugreportFile;
-        final int max = -1; // this is to log metrics for dumpstate duration.
-        File screenshotFile = info.screenshotFiles.isEmpty()
-                ? null : info.screenshotFiles.get(0);
-        // If the screenshot file did not get populated implies this type of bugreport does not
-        // need the screenshot file; setting the file to null so that empty file doesnt get shared
-        if (screenshotFile != null && screenshotFile.length() == 0) {
-            if (screenshotFile.delete()) {
-                Log.d(TAG, "screenshot file deleted successfully.");
-            }
-            info.screenshotFiles.remove(0);
-            // TODO(b/136066578): Will soon stop using the below variable as it is a no-op in
-            // API flow and the screenshotFile value is read from info.screenshotFiles
-            screenshotFile = null;
-        }
-        // TODO: Since we are passing id to the function, it should be able to find the info linked
-        // to the id and therefore use the value of shareTitle and shareDescription.
-        onBugreportFinished(id, bugreportFile, screenshotFile, info.shareTitle,
-                info.shareDescription, max);
-    }
-
-
-    /**
      * Wraps up bugreport generation and triggers a notification to share the bugreport.
      */
-    private void onBugreportFinished(int id, File bugreportFile, @Nullable File screenshotFile,
-        String shareTitle, String shareDescription, int max) {
-        mInfoDialog.onBugreportFinished();
-        BugreportInfo info = getInfo(id);
-        if (info == null) {
-            // Happens when BUGREPORT_FINISHED was received without a BUGREPORT_STARTED first.
-            Log.v(TAG, "Creating info for untracked ID " + id);
-            info = new BugreportInfo(mContext, id);
-            DumpstateListener dumpstateListener = new DumpstateListener(info);
-            mBugreportInfos.put(id, info);
-        }
-        if (!mUsingBugreportApi) {
-            // Rename in API flow happens before sending the broadcast for remote bugreport (to
-            // handle renaming before sending broadcasts)
-            info.renameScreenshots(mScreenshotsDir);
-            // API workflow already has the bugreport file. This was required in legacy flow, when
-            // FINISHED broadcast would send the final bugreport files.
-            // TODO(b/136066578): Change function definition to not include bugreport/screenshot
-            // file in params
-            info.bugreportFile = bugreportFile;
-            if (screenshotFile != null) {
-                info.addScreenshot(screenshotFile);
-            }
-        }
-
-        if (max != -1) {
-            MetricsLogger.histogram(this, "dumpstate_duration", max);
-            info.max = max;
-        }
-
-        if (!TextUtils.isEmpty(shareTitle)) {
-            info.title = shareTitle;
-            if (!TextUtils.isEmpty(shareDescription)) {
-                info.shareDescription= shareDescription;
-            }
-            Log.d(TAG, "Bugreport title is " + info.title + ","
-                    + " shareDescription is " + info.shareDescription);
-        }
+    private void onBugreportFinished(BugreportInfo info) {
+        Log.d(TAG, "Bugreport finished with title: " + info.title
+                + " and shareDescription:  " + info.shareDescription);
         info.finished = true;
 
         // Stop running on foreground, otherwise share notification cannot be dismissed.
-        stopForegroundWhenDone(id);
+        stopForegroundWhenDone(info.id);
 
         triggerLocalNotification(mContext, info);
     }
@@ -1214,7 +1034,11 @@
     /**
      * Build {@link Intent} that can be used to share the given bugreport.
      */
-    private static Intent buildSendIntent(Context context, BugreportInfo info) {
+    private static Intent buildSendIntent(Context context, BugreportInfo info,
+            File screenshotsDir) {
+        // Rename files (if required) before sharing
+        info.renameBugreportFile();
+        info.renameScreenshots(screenshotsDir);
         // Files are kept on private storage, so turn into Uris that we can
         // grant temporary permissions for.
         final Uri bugreportUri;
@@ -1300,7 +1124,7 @@
 
         addDetailsToZipFile(info);
 
-        final Intent sendIntent = buildSendIntent(mContext, info);
+        final Intent sendIntent = buildSendIntent(mContext, info, mScreenshotsDir);
         if (sendIntent == null) {
             Log.w(TAG, "Stopping progres on ID " + id + " because share intent could not be built");
             synchronized (mLock) {
@@ -1628,12 +1452,11 @@
         }
         String action = intent.getAction();
         if (action == null) {
-            // Happens when BugreportReceiver calls startService...
+            // Happens when startService is called...
             action = "no action";
         }
         final StringBuilder buffer = new StringBuilder(action).append(" extras: ");
         addExtra(buffer, intent, EXTRA_ID);
-        addExtra(buffer, intent, EXTRA_PID);
         addExtra(buffer, intent, EXTRA_MAX);
         addExtra(buffer, intent, EXTRA_NAME);
         addExtra(buffer, intent, EXTRA_DESCRIPTION);
@@ -1678,15 +1501,6 @@
     }
 
     /**
-     * Updates the system property used by {@code dumpstate} to rename the final bugreport files.
-     */
-    private boolean setBugreportNameProperty(int pid, String name) {
-        Log.d(TAG, "Updating bugreport name to " + name);
-        final String key = DUMPSTATE_PREFIX + pid + NAME_SUFFIX;
-        return setSystemProperty(key, name);
-    }
-
-    /**
      * Updates the user-provided details of a bugreport.
      */
     private void updateBugreportInfo(int id, String name, String title, String description) {
@@ -1770,30 +1584,6 @@
         private AlertDialog mDialog;
         private Button mOkButton;
         private int mId;
-        private int mPid;
-
-        /**
-         * Last "committed" value of the bugreport name.
-         * <p>
-         * Once initially set, it's only updated when user clicks the OK button.
-         */
-        private String mSavedName;
-
-        /**
-         * Last value of the bugreport name as entered by the user.
-         * <p>
-         * Every time it's changed the equivalent system property is changed as well, but if the
-         * user clicks CANCEL, the old value (stored on {@code mSavedName} is restored.
-         * <p>
-         * This logic handles the corner-case scenario where {@code dumpstate} finishes after the
-         * user changed the name but didn't clicked OK yet (for example, because the user is typing
-         * the description). The only drawback is that if the user changes the name while
-         * {@code dumpstate} is running but clicks CANCEL after it finishes, then the final name
-         * will be the one that has been canceled. But when {@code dumpstate} finishes the {code
-         * name} UI is disabled and the old name restored anyways, so the user will be "alerted" of
-         * such drawback.
-         */
-        private String mTempName;
 
         /**
          * Sets its internal state and displays the dialog.
@@ -1813,18 +1603,6 @@
                 mInfoName = (EditText) view.findViewById(R.id.name);
                 mInfoTitle = (EditText) view.findViewById(R.id.title);
                 mInfoDescription = (EditText) view.findViewById(R.id.description);
-
-                mInfoName.setOnFocusChangeListener(new OnFocusChangeListener() {
-
-                    @Override
-                    public void onFocusChange(View v, boolean hasFocus) {
-                        if (hasFocus) {
-                            return;
-                        }
-                        sanitizeName(info);
-                    }
-                });
-
                 mDialog = new AlertDialog.Builder(themedContext)
                         .setView(view)
                         .setTitle(dialogTitle)
@@ -1839,15 +1617,6 @@
                                     {
                                         MetricsLogger.action(context,
                                                 MetricsEvent.ACTION_BUGREPORT_DETAILS_CANCELED);
-                                        if (!mTempName.equals(mSavedName)) {
-                                            // Must restore bugreport's name since it was changed
-                                            // before user clicked OK.
-                                            if (mUsingBugreportApi) {
-                                                info.name = mSavedName;
-                                            } else {
-                                                setBugreportNameProperty(mPid, mSavedName);
-                                            }
-                                        }
                                     }
                                 })
                         .create();
@@ -1866,9 +1635,7 @@
             }
 
             // Then set fields.
-            mSavedName = mTempName = info.name;
             mId = info.id;
-            mPid = info.pid;
             if (!TextUtils.isEmpty(info.name)) {
                 mInfoName.setText(info.name);
             }
@@ -1895,7 +1662,7 @@
                     @Override
                     public void onClick(View view) {
                         MetricsLogger.action(context, MetricsEvent.ACTION_BUGREPORT_DETAILS_SAVED);
-                        sanitizeName(info);
+                        sanitizeName(info.name);
                         final String name = mInfoName.getText().toString();
                         final String title = mInfoTitle.getText().toString();
                         final String description = mInfoDescription.getText().toString();
@@ -1911,9 +1678,9 @@
          * Sanitizes the user-provided value for the {@code name} field, automatically replacing
          * invalid characters if necessary.
          */
-        private void sanitizeName(BugreportInfo info) {
+        private void sanitizeName(String savedName) {
             String name = mInfoName.getText().toString();
-            if (name.equals(mTempName)) {
+            if (name.equals(savedName)) {
                 if (DEBUG) Log.v(TAG, "name didn't change, no need to sanitize: " + name);
                 return;
             }
@@ -1933,28 +1700,6 @@
                 name = safeName.toString();
                 mInfoName.setText(name);
             }
-            mTempName = name;
-            if (mUsingBugreportApi) {
-                info.name = name;
-            } else {
-                // Must update system property for the cases where dumpstate finishes
-                // while the user is still entering other fields (like title or
-                // description)
-                setBugreportNameProperty(mPid, name);
-            }
-        }
-
-       /**
-         * Notifies the dialog that the bugreport has finished so it disables the {@code name}
-         * field.
-         * <p>Once the bugreport is finished dumpstate has already generated the final files, so
-         * changing the name would have no effect.
-         */
-        void onBugreportFinished() {
-            if (mInfoName != null) {
-                mInfoName.setEnabled(false);
-                mInfoName.setText(mSavedName);
-            }
         }
 
         void cancel() {
@@ -1976,18 +1721,10 @@
         int id;
 
         /**
-         * {@code pid} of the {@code dumpstate} process generating the bugreport.
-         * pid is unused in the API flow
-         * TODO(b/136066578): Remove pid
-         */
-        final int pid;
-
-        /**
          * Prefix name of the bugreport, this is uneditable.
          * The baseName consists of the string "bugreport" + deviceName + buildID
          * This will end with the string "wifi"/"telephony" for wifi/telephony bugreports.
          * Bugreport zip file name  = "<baseName>-<name>.zip"
-         * Bugreport png file name = "<baseName>-<name>.png"
          */
         String baseName;
 
@@ -1998,6 +1735,12 @@
         String name;
 
         /**
+         * Initial value of the field name. This is required to rename the files later on, as they
+         * are created using initial value of name.
+         */
+        String initialName;
+
+        /**
          * User-provided, one-line summary of the bug; when set, will be used as the subject
          * of the {@link Intent#ACTION_SEND_MULTIPLE} intent.
          */
@@ -2063,12 +1806,6 @@
         boolean finished;
 
         /**
-         * Whether this bugreport is using API workflow.
-         * TODO(b/136066578): Remove when legacy bugreport methods are removed
-         */
-        boolean usingApi;
-
-        /**
          * Whether the details entries have been added to the bugreport yet.
          */
         boolean addingDetailsToZip;
@@ -2092,42 +1829,18 @@
         int type;
 
         /**
-         * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_STARTED.
-         */
-        BugreportInfo(Context context, int id, int pid, String name, int max) {
-            // bugreports triggered by STARTED broadcast do not use callback functions,
-            // onFinished() callback method is the only function where type is used.
-            // Set type to -1 as it is unused in this workflow.
-            // This constructor will soon be removed.
-            this(context, pid, "" /* dumpstate handles basename */, name, max, null, null, -1,
-                    false);
-            this.id = id;
-        }
-
-        /**
          * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_REQUESTED.
          */
-        BugreportInfo(Context context, int pid, String baseName, String name, int max,
+        BugreportInfo(Context context, String baseName, String name, int max,
                 @Nullable String shareTitle, @Nullable String shareDescription,
-                @BugreportParams.BugreportMode int type, boolean usingApi) {
+                @BugreportParams.BugreportMode int type) {
             this.context = context;
-            this.pid = pid;
-            this.name = name;
+            this.name = this.initialName = name;
             this.max = this.realMax = max;
             this.shareTitle = shareTitle == null ? "" : shareTitle;
             this.shareDescription = shareDescription == null ? "" : shareDescription;
             this.type = type;
             this.baseName = baseName;
-            this.usingApi = usingApi;
-        }
-
-        /**
-         * Constructor for untracked bugreports - typically called upon receiving BUGREPORT_FINISHED
-         * without a previous call to BUGREPORT_STARTED.
-         */
-        BugreportInfo(Context context, int id) {
-            this(context, id, id, null, 0);
-            this.finished = true;
         }
 
         ParcelFileDescriptor createBugreportFd() {
@@ -2136,17 +1849,24 @@
         }
 
         ParcelFileDescriptor createScreenshotFd() {
-            File screenshotFile = new File(BUGREPORT_DIR, getFileName(this, ".png"));
+            File screenshotFile = new File(BUGREPORT_DIR, getScreenshotName("default"));
             addScreenshot(screenshotFile);
             return createReadWriteFile(screenshotFile);
         }
 
         /**
-         * Gets the name for next screenshot file.
+         * Gets the name for next user triggered screenshot file.
          */
         String getPathNextScreenshot() {
             screenshotCounter ++;
-            return "screenshot-" + pid + "-" + screenshotCounter + ".png";
+            return getScreenshotName(Integer.toString(screenshotCounter));
+        }
+
+        /**
+         * Gets the name for screenshot file based on the suffix that is passed.
+         */
+        String getScreenshotName(String suffix) {
+            return "screenshot-" + initialName + "-" + suffix + ".png";
         }
 
         /**
@@ -2157,7 +1877,8 @@
         }
 
         /**
-         * Rename all screenshots files so that they contain the user-generated name instead of pid.
+         * Rename all screenshots files so that they contain the new {@code name} instead of the
+         * {@code initialName} if user has changed it.
          */
         void renameScreenshots(File screenshotDir) {
             if (TextUtils.isEmpty(name)) {
@@ -2166,22 +1887,21 @@
             final List<File> renamedFiles = new ArrayList<>(screenshotFiles.size());
             for (File oldFile : screenshotFiles) {
                 final String oldName = oldFile.getName();
-                final String newName;
-                if (usingApi) {
-                    newName = getFileName(this, ".png");
-                } else {
-                    newName = oldName.replaceFirst(Integer.toString(pid), name);
-                }
+                final String newName = oldName.replaceFirst(initialName, name);
                 final File newFile;
                 if (!newName.equals(oldName)) {
                     final File renamedFile = new File(screenshotDir, newName);
                     Log.d(TAG, "Renaming screenshot file " + oldFile + " to " + renamedFile);
                     newFile = oldFile.renameTo(renamedFile) ? renamedFile : oldFile;
                 } else {
-                    Log.w(TAG, "Name didn't change: " + oldName); // Shouldn't happen.
+                    Log.w(TAG, "Name didn't change: " + oldName);
                     newFile = oldFile;
                 }
-                renamedFiles.add(newFile);
+                if (newFile.length() > 0) {
+                    renamedFiles.add(newFile);
+                } else if (newFile.delete()) {
+                    Log.d(TAG, "screenshot file: " + newFile + "deleted successfully.");
+                }
             }
             screenshotFiles = renamedFiles;
         }
@@ -2215,11 +1935,10 @@
 
             final StringBuilder builder = new StringBuilder()
                     .append("\tid: ").append(id)
-                    .append(", pid: ").append(pid)
                     .append(", baseName: ").append(baseName)
                     .append(", name: ").append(name)
+                    .append(", initialName: ").append(initialName)
                     .append(", finished: ").append(finished)
-                    .append(", usingApi: ").append(usingApi)
                     .append("\n\ttitle: ").append(title)
                     .append("\n\tdescription: ");
             if (description == null) {
@@ -2250,9 +1969,9 @@
         protected BugreportInfo(Parcel in) {
             context = null;
             id = in.readInt();
-            pid = in.readInt();
             baseName = in.readString();
             name = in.readString();
+            initialName = in.readString();
             title = in.readString();
             description = in.readString();
             max = in.readInt();
@@ -2269,7 +1988,6 @@
             }
 
             finished = in.readInt() == 1;
-            usingApi = in.readInt() == 1;
             screenshotCounter = in.readInt();
             shareDescription = in.readString();
             shareTitle = in.readString();
@@ -2278,9 +1996,9 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(id);
-            dest.writeInt(pid);
             dest.writeString(baseName);
             dest.writeString(name);
+            dest.writeString(initialName);
             dest.writeString(title);
             dest.writeString(description);
             dest.writeInt(max);
@@ -2297,7 +2015,6 @@
             }
 
             dest.writeInt(finished ? 1 : 0);
-            dest.writeInt(usingApi ? 1 : 0);
             dest.writeInt(screenshotCounter);
             dest.writeString(shareDescription);
             dest.writeString(shareTitle);
@@ -2333,80 +2050,6 @@
 
     }
 
-    private final class DumpstateListener extends IDumpstateListener.Stub
-        implements DeathRecipient {
-
-        private final BugreportInfo info;
-        private IDumpstateToken token;
-
-        DumpstateListener(BugreportInfo info) {
-            this.info = info;
-        }
-
-        /**
-         * Connects to the {@code dumpstate} binder to receive updates.
-         */
-        boolean connect() {
-            if (token != null) {
-                Log.d(TAG, "connect(): " + info.id + " already connected");
-                return true;
-            }
-            final IBinder service = ServiceManager.getService("dumpstate");
-            if (service == null) {
-                Log.d(TAG, "dumpstate service not bound yet");
-                return true;
-            }
-            final IDumpstate dumpstate = IDumpstate.Stub.asInterface(service);
-            try {
-                token = dumpstate.setListener("Shell", this, /* perSectionDetails= */ false);
-                if (token != null) {
-                    token.asBinder().linkToDeath(this, 0);
-                }
-            } catch (Exception e) {
-                Log.e(TAG, "Could not set dumpstate listener: " + e);
-            }
-            return token != null;
-        }
-
-        @Override
-        public void binderDied() {
-            if (!info.finished) {
-                // TODO: linkToDeath() might be called BEFORE Shell received the
-                // BUGREPORT_FINISHED broadcast, in which case the statements below
-                // spam logcat (but are harmless).
-                // The right, long-term solution is to provide an onFinished() callback
-                // on IDumpstateListener and call it instead of using a broadcast.
-                Log.w(TAG, "Dumpstate process died:\n" + info);
-                synchronized (mLock) {
-                    stopProgressLocked(info.id);
-                }
-            }
-            token.asBinder().unlinkToDeath(this, 0);
-        }
-
-        @Override
-        public void onProgress(int progress) throws RemoteException {
-            synchronized (mLock) {
-                checkProgressUpdatedLocked(info, progress);
-            }
-        }
-
-        @Override
-        public void onError(int errorCode) throws RemoteException {
-            // TODO(b/111441001): implement
-        }
-
-        @Override
-        public void onFinished() throws RemoteException {
-            // TODO(b/111441001): implement
-        }
-
-        public void dump(String prefix, PrintWriter pw) {
-            pw.print(prefix); pw.print("token: "); pw.println(token);
-        }
-
-    }
-
     @GuardedBy("mLock")
     private void checkProgressUpdatedLocked(BugreportInfo info, int progress) {
         if (progress > CAPPED_PROGRESS) {
@@ -2418,11 +2061,11 @@
     private void updateProgressInfo(BugreportInfo info, int progress, int max) {
         if (DEBUG) {
             if (progress != info.progress) {
-                Log.v(TAG, "Updating progress for PID " + info.pid + "(id: " + info.id
+                Log.v(TAG, "Updating progress for name " + info.name + "(id: " + info.id
                         + ") from " + info.progress + " to " + progress);
             }
             if (max != info.max) {
-                Log.v(TAG, "Updating max progress for PID " + info.pid + "(id: " + info.id
+                Log.v(TAG, "Updating max progress for name " + info.name + "(id: " + info.id
                         + ") from " + info.max + " to " + max);
             }
         }
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
deleted file mode 100644
index 15ce90f..0000000
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2013 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.shell;
-
-import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
-import static com.android.shell.BugreportProgressService.EXTRA_ORIGINAL_INTENT;
-import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
-import static com.android.shell.BugreportProgressService.getFileExtra;
-import static com.android.shell.BugreportProgressService.dumpIntent;
-
-import java.io.File;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.FileUtils;
-import android.text.format.DateUtils;
-import android.util.Log;
-
-/**
- * Receiver that handles finished bugreports, usually by attaching them to an
- * {@link Intent#ACTION_SEND_MULTIPLE}.
- */
-public class BugreportReceiver extends BroadcastReceiver {
-    private static final String TAG = "BugreportReceiver";
-
-    /**
-     * Always keep the newest 8 bugreport files.
-     */
-    private static final int MIN_KEEP_COUNT = 8;
-
-    /**
-     * Always keep bugreports taken in the last week.
-     */
-    private static final long MIN_KEEP_AGE = DateUtils.WEEK_IN_MILLIS;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        Log.d(TAG, "onReceive(): " + dumpIntent(intent));
-        // Clean up older bugreports in background
-        cleanupOldFiles(this, intent, INTENT_BUGREPORT_FINISHED, MIN_KEEP_COUNT, MIN_KEEP_AGE);
-
-        // Delegate intent handling to service.
-        Intent serviceIntent = new Intent(context, BugreportProgressService.class);
-        serviceIntent.putExtra(EXTRA_ORIGINAL_INTENT, intent);
-        context.startService(serviceIntent);
-    }
-
-    static void cleanupOldFiles(BroadcastReceiver br, Intent intent, String expectedAction,
-            final int minCount, final long minAge) {
-        if (!expectedAction.equals(intent.getAction())) {
-            return;
-        }
-        final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
-        if (bugreportFile == null || !bugreportFile.exists()) {
-            Log.e(TAG, "Not deleting old files because file " + bugreportFile + " doesn't exist");
-            return;
-        }
-        final PendingResult result = br.goAsync();
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                try {
-                    FileUtils.deleteOlderFiles(bugreportFile.getParentFile(), minCount, minAge);
-                } catch (RuntimeException e) {
-                    Log.e(TAG, "RuntimeException deleting old files", e);
-                }
-                result.finish();
-                return null;
-            }
-        }.execute();
-    }
-}
diff --git a/packages/Shell/src/com/android/shell/RemoteBugreportReceiver.java b/packages/Shell/src/com/android/shell/RemoteBugreportReceiver.java
deleted file mode 100644
index 634c3b4..0000000
--- a/packages/Shell/src/com/android/shell/RemoteBugreportReceiver.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2015 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.shell;
-
-import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
-import static com.android.shell.BugreportProgressService.INTENT_REMOTE_BUGREPORT_FINISHED;
-import static com.android.shell.BugreportProgressService.getFileExtra;
-import static com.android.shell.BugreportProgressService.getUri;
-import static com.android.shell.BugreportReceiver.cleanupOldFiles;
-
-import java.io.File;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.UserHandle;
-import android.text.format.DateUtils;
-
-/**
- * Receiver that handles finished remote bugreports, by re-sending
- * the intent with appended bugreport zip file URI.
- *
- * <p> Remote bugreport never contains a screenshot.
- */
-public class RemoteBugreportReceiver extends BroadcastReceiver {
-
-    private static final String BUGREPORT_MIMETYPE = "application/vnd.android.bugreport";
-
-    /** Always keep just the last remote bugreport's files around. */
-    private static final int REMOTE_BUGREPORT_FILES_AMOUNT = 3;
-
-    /** Always keep remote bugreport files created in the last day. */
-    private static final long MIN_KEEP_AGE = DateUtils.DAY_IN_MILLIS;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        cleanupOldFiles(this, intent, INTENT_REMOTE_BUGREPORT_FINISHED,
-                REMOTE_BUGREPORT_FILES_AMOUNT, MIN_KEEP_AGE);
-
-        final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
-        final Uri bugreportUri = getUri(context, bugreportFile);
-        final String bugreportHash = intent.getStringExtra(
-                DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH);
-
-        final Intent newIntent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
-        newIntent.setDataAndType(bugreportUri, BUGREPORT_MIMETYPE);
-        newIntent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash);
-        context.sendBroadcastAsUser(newIntent, UserHandle.SYSTEM,
-                android.Manifest.permission.DUMP);
-    }
-}
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 3a71632..bb298e9 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -29,10 +29,8 @@
 import static com.android.shell.BugreportProgressService.EXTRA_ID;
 import static com.android.shell.BugreportProgressService.EXTRA_MAX;
 import static com.android.shell.BugreportProgressService.EXTRA_NAME;
-import static com.android.shell.BugreportProgressService.EXTRA_PID;
 import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
 import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
-import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
 import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
 
 import static org.junit.Assert.assertEquals;
@@ -145,6 +143,10 @@
     private static final String TITLE2 = "Master of the Universe";
     private static final String DESCRIPTION = "One's description...";
     private static final String DESCRIPTION2 = "...is another's treasure.";
+    // TODO(b/143130523): Fix (update) tests and add to presubmit
+    private static final String EXTRA_PID = "android.intent.extra.PID";
+    private static final String INTENT_BUGREPORT_STARTED =
+            "com.android.internal.intent.action.BUGREPORT_STARTED";
 
     private static final String NO_DESCRIPTION = null;
     private static final String NO_NAME = null;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java
new file mode 100644
index 0000000..802a8da
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java
@@ -0,0 +1,72 @@
+/*
+ * 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.systemui.plugins;
+
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/** Custom logic that can extract a PeopleHub "person" from a notification. */
+@ProvidesInterface(
+        action = NotificationPersonExtractorPlugin.ACTION,
+        version = NotificationPersonExtractorPlugin.VERSION)
+@DependsOn(target = NotificationPersonExtractorPlugin.PersonData.class)
+public interface NotificationPersonExtractorPlugin extends Plugin {
+
+    String ACTION = "com.android.systemui.action.PEOPLE_HUB_PERSON_EXTRACTOR";
+    int VERSION = 0;
+
+    /**
+     * Attempts to extract a person from a notification. Returns {@code null} if one is not found.
+     */
+    @Nullable PersonData extractPerson(StatusBarNotification sbn);
+
+    /**
+     * Attempts to extract a person id from a notification. Returns {@code null} if one is not
+     * found.
+     *
+     * This method can be overridden in order to provide a faster implementation.
+     */
+    @Nullable
+    default String extractPersonKey(StatusBarNotification sbn) {
+        return extractPerson(sbn).key;
+    }
+
+    /** A person to be surfaced in PeopleHub. */
+    @ProvidesInterface(version = PersonData.VERSION)
+    final class PersonData {
+
+        public static final int VERSION = 0;
+
+        public final String key;
+        public final CharSequence name;
+        public final Drawable avatar;
+        public final PendingIntent clickIntent;
+
+        public PersonData(String key, CharSequence name, Drawable avatar,
+                PendingIntent clickIntent) {
+            this.key = key;
+            this.name = name;
+            this.avatar = avatar;
+            this.clickIntent = clickIntent;
+        }
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
index fe547a0a..b21a9f7 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
@@ -95,9 +95,12 @@
         default void onDozeAmountChanged(float linear, float eased) {}
 
         /**
-         * Callback to be notified when the sysui visibility changes
+         * Callback to be notified when the fullscreen or immersive state changes.
+         *
+         * @param isFullscreen if any of the system bar is hidden by the focused window.
+         * @param isImmersive if the navigation bar can stay hidden when the display gets tapped.
          */
-        default void onSystemUiVisibilityChanged(int visibility) {}
+        default void onFullscreenStateChanged(boolean isFullscreen, boolean isImmersive) {}
 
         /**
          * Callback to be notified when the pulsing state changes
diff --git a/packages/SystemUI/res/layout/home_controls.xml b/packages/SystemUI/res/layout/home_controls.xml
index bb971c2..b9a6a48 100644
--- a/packages/SystemUI/res/layout/home_controls.xml
+++ b/packages/SystemUI/res/layout/home_controls.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/home_controls_layout"
     android:layout_width="match_parent"
@@ -8,6 +8,5 @@
     android:visibility="gone"
     android:padding="8dp"
     android:layout_margin="5dp"
-    android:background="?android:attr/colorBackgroundFloating"
-    android:orientation="vertical">
-</LinearLayout>
+    android:background="?android:attr/colorBackgroundFloating">
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml
new file mode 100644
index 0000000..f0ac08b
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_strip.xml
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<com.android.systemui.statusbar.notification.stack.PeopleHubView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="105dp">
+
+    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
+        android:id="@+id/backgroundNormal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
+        android:id="@+id/backgroundDimmed"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <LinearLayout
+        android:id="@+id/people_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"
+        android:gravity="center"
+        android:orientation="horizontal">
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <LinearLayout
+            android:layout_width="70dp"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:visibility="invisible">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="36dp"
+                android:layout_height="36dp"
+                android:scaleType="fitCenter"
+            />
+
+            <TextView
+                android:id="@+id/person_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:ellipsize="end"
+                android:maxLines="2"
+                android:textAlignment="center"
+            />
+
+        </LinearLayout>
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <LinearLayout
+            android:layout_width="70dp"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:visibility="invisible">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="36dp"
+                android:layout_height="36dp"
+                android:scaleType="fitCenter"
+            />
+
+            <TextView
+                android:id="@+id/person_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:ellipsize="end"
+                android:maxLines="2"
+                android:textAlignment="center"
+            />
+
+        </LinearLayout>
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <LinearLayout
+            android:layout_width="70dp"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:visibility="invisible">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="36dp"
+                android:layout_height="36dp"
+                android:scaleType="fitCenter"
+            />
+
+            <TextView
+                android:id="@+id/person_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:ellipsize="end"
+                android:maxLines="2"
+                android:textAlignment="center"
+            />
+
+        </LinearLayout>
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <LinearLayout
+            android:layout_width="70dp"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:visibility="invisible">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="36dp"
+                android:layout_height="36dp"
+                android:scaleType="fitCenter"
+            />
+
+            <TextView
+                android:id="@+id/person_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:ellipsize="end"
+                android:maxLines="2"
+                android:textAlignment="center"
+            />
+
+        </LinearLayout>
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+        <LinearLayout
+            android:layout_width="70dp"
+            android:layout_height="match_parent"
+            android:gravity="center_horizontal"
+            android:orientation="vertical"
+            android:visibility="invisible">
+
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="36dp"
+                android:layout_height="36dp"
+                android:scaleType="fitCenter"
+            />
+
+            <TextView
+                android:id="@+id/person_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:ellipsize="end"
+                android:maxLines="2"
+                android:textAlignment="center"
+            />
+
+        </LinearLayout>
+
+        <View
+            android:layout_width="8dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+        />
+
+    </LinearLayout>
+
+    <com.android.systemui.statusbar.notification.FakeShadowView
+        android:id="@+id/fake_shadow"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</com.android.systemui.statusbar.notification.stack.PeopleHubView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qqs_media_panel.xml b/packages/SystemUI/res/layout/qqs_media_panel.xml
new file mode 100644
index 0000000..1189371
--- /dev/null
+++ b/packages/SystemUI/res/layout/qqs_media_panel.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<!-- Layout for QQS media controls -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/qqs_media_controls"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:gravity="center"
+    android:padding="10dp"
+    >
+    <!-- Top line: icon + artist name -->
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:clipChildren="false"
+        android:gravity="center"
+        >
+        <com.android.internal.widget.CachingIconView
+            android:id="@+id/icon"
+            android:layout_width="15dp"
+            android:layout_height="15dp"
+            android:layout_marginEnd="5dp"
+        />
+        <TextView
+            android:id="@+id/header_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:singleLine="true"
+        />
+    </LinearLayout>
+
+    <!-- Second line: song name -->
+    <TextView
+        android:id="@+id/header_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:fontFamily="@*android:string/config_bodyFontFamily"
+        android:gravity="center"/>
+
+    <!-- Bottom section: controls -->
+    <LinearLayout
+        android:id="@+id/media_actions"
+        android:orientation="horizontal"
+        android:layoutDirection="ltr"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        >
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action0"
+        />
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action1"
+        />
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action2"
+        />
+    </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_media_panel.xml b/packages/SystemUI/res/layout/qs_media_panel.xml
new file mode 100644
index 0000000..dd42276
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_media_panel.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<!-- Layout for media controls inside QSPanel carousel -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/qs_media_controls"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:gravity="center_horizontal|fill_vertical"
+    android:padding="10dp"
+    >
+
+    <!-- placeholder for notification header -->
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/header"
+        android:padding="3dp"
+        android:layout_marginEnd="-12dp"
+        />
+
+    <!-- Top line: artist name -->
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        >
+        <TextView
+            android:id="@+id/header_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+            android:singleLine="true"
+        />
+    </LinearLayout>
+
+    <!-- Second line: song name -->
+    <TextView
+        android:id="@+id/header_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:fontFamily="@*android:string/config_bodyFontFamily"
+        android:gravity="center"/>
+
+    <!-- Bottom section: controls -->
+    <LinearLayout
+        android:id="@+id/media_actions"
+        android:orientation="horizontal"
+        android:layoutDirection="ltr"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        >
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action0"
+        />
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action1"
+        />
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action2"
+        />
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action3"
+        />
+        <ImageButton
+            style="@android:style/Widget.Material.Button.Borderless.Small"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="8dp"
+            android:layout_marginEnd="2dp"
+            android:gravity="center"
+            android:visibility="gone"
+            android:id="@+id/action4"
+        />
+    </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index ed18dc7..e99b917 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -43,7 +43,7 @@
     <com.android.systemui.qs.QuickQSPanel
         android:id="@+id/quick_qs_panel"
         android:layout_width="match_parent"
-        android:layout_height="48dp"
+        android:layout_height="wrap_content"
         android:layout_below="@id/quick_qs_status_icons"
         android:layout_marginStart="@dimen/qs_header_tile_margin_horizontal"
         android:layout_marginEnd="@dimen/qs_header_tile_margin_horizontal"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index b0b4615..e86fb70 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Stel invoer metodes op"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fisiese sleutelbord"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Laat <xliff:g id="APPLICATION">%1$s</xliff:g> toe om by <xliff:g id="USB_DEVICE">%2$s</xliff:g> in te gaan?\nOpneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel vasvang."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te hanteer?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te hanteer?\nOpneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel vasvang."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> te hanteer?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Geen geïnstalleerde programme werk met hierdie USB-toebehoorsel nie. Vind meer uit oor hierdie toebehoorsel by <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-toebehoorsel"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bevestig"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tik op Bevestig om te voltooi"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Gestaaf"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gebruik PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gebruik patroon"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gebruik wagwoord"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Verkeerde PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Verkeerde patroon"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Verkeerde wagwoord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Te veel verkeerde pogings.\nProbeer oor <xliff:g id="NUMBER">%d</xliff:g> sekondes weer."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Raak die vingerafdruksensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Vingerafdrukikoon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Soek tans vir jou …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Kennisgewings"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flitslig"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera in gebruik"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiele data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datagebruik"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Oorblywende data"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e423c6a..fed9b05 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"የግቤት ስልቶችን አዘጋጅ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"የሚዳሰስ የቁልፍ ሰሌዳ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስ ይፈቀድለት?\nይህ መተግበሪያ የመቅዳት ፈቃድ አልተሰጠውም፣ ነገር ግን በዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅዳት ይችላል።"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲይዘው <xliff:g id="APPLICATION">%1$s</xliff:g> ይክፈት?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> ን <xliff:g id="USB_DEVICE">%2$s</xliff:g> ለማስተናገድ ይከፈት?\nይህ መተግበሪያ የቅጂ ፈቃድ አልተሰጠውም ሆኖም ግን በዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅዳት ይችላል።"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ን እንዲይዘው <xliff:g id="APPLICATION">%1$s</xliff:g> ይክፈት?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ምንም የተጫኑ መተግበሪያዎች ከዚህ የUSB ተቀጥላ ጋር አይሰሩም። በ<xliff:g id="URL">%1$s</xliff:g> ስለዚህ ተቀጥላ የበለጠ ለመረዳት።"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"የUSB  ተቀጥላ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ተረጋግጧል"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ለማጠናቀቅ አረጋግጥን መታ ያድርጉ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"የተረጋገጠ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ፒን ይጠቀሙ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ሥርዓተ ጥለትን ተጠቀም"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"የይለፍ ቃልን ተጠቀም"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"የተሳሳተ ፒን"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"የተሳሳተ ሥርዓተ ጥለት"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"የተሳሳተ የይለፍ ቃል"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ከልክ በላይ ብዙ የተሳሳቱ ሙከራዎች።\nበ<xliff:g id="NUMBER">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"የጣት አሻራ ዳሳሹን ይንኩ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"የጣት አሻራ አዶ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"እርስዎን በመፈለግ ላይ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ማሳወቂያዎች"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"የባትሪ ብርሃን"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ካሜራ ስራ ላይ ነው"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"የውሂብ አጠቃቀም"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ቀሪ ውሂብ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 3b145105..b04df54 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"إعداد أسلوب الإدخال"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"لوحة مفاتيح فعلية"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟\nلم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>؟"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"هل تريد فتح <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"‏هل تريد فتح تطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟\nلم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"هل تريد فتح تطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>؟"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏لا يعمل أي تطبيق مثبت مع ملحق UEB هذا. مزيد من المعلومات عن هذا الملحق على <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏ملحق USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"تمّ التأكيد."</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"يمكنك النقر على \"تأكيد\" لإكمال المهمة."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"مصادقة"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"استخدام رقم تعريف شخصي"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"استخدام نقش"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"استخدام كلمة المرور"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"رقم تعريف شخصي خاطئ"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"نقش غير صحيح"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"كلمة مرور غير صحيحة"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"تم إجراء عدد كبير جدًا من المحاولات غير الصحيحة.\nأعد المحاولة خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"المس زر استشعار بصمة الإصبع"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"رمز بصمة الإصبع"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"جارٍ البحث عن وجهك…"</string>
@@ -388,8 +381,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"الإشعارات"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"الفلاش"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"الكاميرا قيد الاستخدام"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"بيانات الجوّال"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"استخدام البيانات"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"البيانات المتبقية"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index c3ca88a..7efb03c 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ইনপুট পদ্ধতি ছেট আপ কৰক"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"বাস্তৱিক কীব\'ৰ্ড"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ত প্ৰৱেশ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক অনুমতি দিবনে?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_DEVICE">%2$s</xliff:g> এক্সেছ কৰিবলৈ অনুমতি দিবনে?\nএই এপ্‌টোক ৰেকর্ড কৰাৰ অনুমতি দিয়া হোৱা নাই কিন্তু ই এই ইউএছবি ডিভাইচটোৰ জৰিয়তে অডিঅ\' ৰেকর্ড কৰিব পাৰে।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ত প্ৰৱেশ কৰিবলৈ অনুমতি দিবনে?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ক ব্যৱহাৰ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক খোলেনে?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ক ব্যৱহাৰ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক খোলেনে?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ইনষ্টল হৈ থকা কোনো এপে ইউএছবি সহায়ক সামগ্ৰীটো চলাব নোৱাৰে। এই সহায়ক সামগ্ৰীৰ বিষয়ে <xliff:g id="URL">%1$s</xliff:g>ৰ জৰিয়তে অধিক জানক৷"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ইউএছবিৰ সহায়ক সামগ্ৰী"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"নিশ্চিত কৰিলে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"সম্পূৰ্ণ কৰিবলৈ নিশ্চিত কৰক-ত টিপক"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"পিন ব্যৱহাৰ কৰক"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"আৰ্হি ব্যৱহাৰ কৰক"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"পাছৱৰ্ড ব্যৱহাৰ কৰক"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ভুল পিন"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ভুল আৰ্হি"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ভুল পাছৱৰ্ড"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"বহুসংখ্যক ভুল প্ৰয়াস।\n<xliff:g id="NUMBER">%d</xliff:g>ছেকেণ্ডত পুনৰ চেষ্টা কৰক।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"আপোনাৰ মুখমণ্ডল বিচাৰি আছে…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"জাননীসমূহ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ফ্লাশ্বলাইট"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"কেমেৰা ব্যৱহাৰ হৈ আছে"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ম’বাইল ডেটা"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ডেটা ব্যৱহাৰ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"বাকী থকা ডেটা"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 67e24c5..9d85126 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Daxiletmə metodlarını ayarlayın"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziki klaviatura"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?\nBu tətbiqə qeydə almaq icazəsi verilməyib lakin, bu USB vasitəsilə səs yaza bilər."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?\nBu tətbiqə yazmaq icazəsi verilməyib, lakin, bu USB vasitəsilə səs yaza bilər."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Heç bir quraşdırılmış tətbiq bu USB aksesuar ilə işləmir. Bu aksesuar haqqında daha ətraflı məlumatı <xliff:g id="URL">%1$s</xliff:g> adresindən öyrənin"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB aksesuar"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Təsdiqləndi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tamamlamaq üçün \"Təsdiq edin\" seçiminə toxunun"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Doğrulandı"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN istifadə edin"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Model istifadə edin"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Parol istifadə edin"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Yanlış PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Yanlış model"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Yanlış parol"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Həddindən çox yanlış cəhd.\n<xliff:g id="NUMBER">%d</xliff:g> saniyəyə yenidən cəhd edin."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Barmaq izi sensoruna klikləyin"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Barmaq izi ikonası"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Siz axtarılırsınız…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirişlər"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"İşartı"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera istifadə olunur"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data istifadəsi"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Qalan data"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3def744..07c321d6 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Podesi metode unosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizička tastatura"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOva aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> da biste koristili uređaj <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi rukovanja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOva aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> da biste koristili uređaj <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Instalirane aplikacije ne funkcionišu sa ovim USB pomoćnim uređajem. Saznajte više o njemu na adresi <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB pomoćni uređaj"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Dodirnite Potvrdi da biste završili"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Identitet je potvrđen"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Koristite PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Koristite šablon"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Koristite lozinku"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Pogrešan PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pogrešan šablon"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pogrešna lozinka"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Previše netačnih pokušaja.\n Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor za otisak prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otiska prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obaveštenja"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampa"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Koristi se kamera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilni podaci"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Potrošnja podataka"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podataka"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index cdb4ddb..ec73200 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Налада метадаў уводу"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Фізічная клавіятура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Дазволіць праграме <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Даць праграме \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ да прылады \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nУ гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту прыладу USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Дазволіць праграме <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Адкрыць праграму <xliff:g id="APPLICATION">%1$s</xliff:g> для працы з прыладай <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Адкрыць праграму \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", каб выкарыстоўваць прыладу \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nУ гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту USB-прыладу."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Адкрыць праграму <xliff:g id="APPLICATION">%1$s</xliff:g> для працы з прыладай <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Няма ўсталяв. прыкл. для працы з гэтай прыл. USB. Больш падраб. пра гэтую прыл.: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-прылада"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Пацверджана"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Націсніце \"Пацвердзіць\", каб завяршыць"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Распазнана"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Увесці PIN-код"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Выкарыстаць узор разблакіроўкі"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Выкарыстаць пароль"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Няправільны PIN-код"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Няправільны ўзор разблакіроўкі"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Няправільны пароль"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Занадта шмат няўдалых спроб.\nПаспрабуйце зноў праз <xliff:g id="NUMBER">%d</xliff:g> с."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Дакраніцеся да сканера адбіткаў пальцаў"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок адбіткаў пальцаў"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ідзе пошук вашага твару…"</string>
@@ -386,8 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Апавяшчэнні"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ліхтарык"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камера выкарыстоўваецца"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мабільная перадача даных"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Выкарыстанне трафіка"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Засталося трафіку"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index cd22290..6eeae8f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Методи на въвеждане: Настройка"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физическа клавиатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Наистина ли искате да разрешите на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа приложението не е предоставено разрешение за записване, но е възможно да запише звук чрез това USB устройство."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Да се използва ли <xliff:g id="APPLICATION">%1$s</xliff:g> за работата с/ъс <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Искате ли да използвате <xliff:g id="APPLICATION">%1$s</xliff:g> за работа с(ъс) <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nПриложението няма разрешение за записване, но може да записва звук чрез това USB устройство."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Да се използва ли <xliff:g id="APPLICATION">%1$s</xliff:g> за работата с/ъс <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Инстал. приложения не работят с този аксесоар за USB. Научете повече на адрес <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Аксесоар за USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Потвърдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Докоснете „Потвърждаване“ за завършване"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Удостоверено"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Използване на ПИН"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Използване на фигура"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Използване на парола"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Грешен ПИН"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Грешна фигура"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Грешна парола"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Твърде много неправилни опити.\nОпитайте отново след <xliff:g id="NUMBER">%d</xliff:g> секунди."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Докоснете сензора за отпечатъци"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечатък"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Търсим ви…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известия"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фенерче"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камерата се използва"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилни данни"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Пренос на данни"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Оставащи данни"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 11a6e90..8e4e9a1 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ইনপুট পদ্ধতিগুলি সেট-আপ করুন"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ফিজিক্যাল কীবোর্ড"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> কে <xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে দেবেন?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে <xliff:g id="APPLICATION">%1$s</xliff:g>-কে কি অনুমতি দেবেন?\nএই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের মাধ্যমে সেটি অডিও রেকর্ড করতে পারে।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> কে <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> অ্যাক্সেস করতে দেবেন?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ব্যবহার করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> চালু করবেন?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> খুলবেন?\nএই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের মাধ্যমে সেটি অডিও রেকর্ড করতে পারে।"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ব্যবহার করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> চালু করবেন?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ইনস্টল থাকা কোনো অ্যাপ্লিকেশান এই USB যন্ত্রাংশের সাথে কাজ করে না৷ <xliff:g id="URL">%1$s</xliff:g> এ এই যন্ত্রাংশের সম্পর্কে আরও জানুন৷"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB যন্ত্রাংশ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"কনফার্ম করা হয়েছে"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"সম্পূর্ণ করতে \'কনফার্ম করুন\' বোতামে ট্যাপ করুন"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"প্রমাণীকৃত"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"পিন ব্যবহার করুন"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"প্যাটার্ন ব্যবহার করুন"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"পাসওয়ার্ড ব্যবহার করুন"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ভুল পিন"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ভুল প্যাটার্ন"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ভুল পাসওয়ার্ড"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"অনেকবার ভুল চেষ্টা করা হয়েছে। \n<xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"আঙ্গুলের ছাপের সেন্সর স্পর্শ করুন"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"আঙ্গুলের ছাপের আইকন"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"আপনার জন্য খোঁজা হচ্ছে…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"বিজ্ঞপ্তি"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ফ্ল্যাশলাইট"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ক্যামেরা ব্যবহার করা হচ্ছে"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"মোবাইল ডেটা"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ডেটার ব্যবহার"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"অবশিষ্ট ডেটা"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 7eaa9c4..c5f94bd 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Postavljanje načina unosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizička tastatura"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOvoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup dodatku: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje uređajem: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite li upravljati uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g> putem aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>?\nOvoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje dodatkom: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nema instaliranih aplikacija za ovaj USB uređaj. Saznajte više o uređaju na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB periferni uređaj"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Dodirnite Potvrdi da završite"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentificirano"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Koristi PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Koristi uzorak"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Koristi lozinku"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Pogrešan PIN kôd"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pogrešan uzorak"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pogrešna lozinka"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Previše pogrešnih pokušaja.\n Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor za otisak prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona za otisak prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavještenja"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svjetiljka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera u upotrebi"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Prijenos podataka na mobilnoj mreži"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Prijenos podataka"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podataka"</string>
@@ -480,7 +472,7 @@
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Izlaganje osjetljivih podataka za vrijeme emitiranja/snimanja"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj opet"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Očisti sve"</string>
-    <string name="manage_notifications_text" msgid="2386728145475108753">"Upravljaj"</string>
+    <string name="manage_notifications_text" msgid="2386728145475108753">"Upravljajte"</string>
     <string name="notification_section_header_gentle" msgid="4372438504154095677">"Nečujna obavještenja"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Obriši sva nečujna obavještenja"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Obavještenja su pauzirana načinom rada Ne ometaj"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 3bd72b3..2ae91dd 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura els mètodes d\'entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclat físic"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAquesta aplicació no té permís de gravació, però pot capturar àudio a través d\'aquest dispositiu USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vols obrir <xliff:g id="APPLICATION">%1$s</xliff:g> per gestionar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vols obrir <xliff:g id="APPLICATION">%1$s</xliff:g> per gestionar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Les aplicacions instal·lades no funcionen amb l\'accessori USB. Més informació: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessori USB"</string>
@@ -110,8 +111,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"Telèfon"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Assistència per veu"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Desbloqueja"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"S\'està esperant l\'empremta digital"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Desbloqueja sense utilitzar l\'empremta digital"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"S\'està esperant l\'empremta dactilar"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Desbloqueja sense utilitzar l\'empremta dactilar"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"S\'està escanejant la cara"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Envia"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Gestiona les notificacions"</string>
@@ -128,22 +129,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toca Confirma per completar"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticat"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor d\'empremtes digitals"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona d\'empremta digital"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utilitza el PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utilitza el patró"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utilitza la contrasenya"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorrecte"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Patró incorrecte"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Contrasenya incorrecta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Has superat el nombre d\'intents incorrectes permesos.\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor d\'empremtes dactilars"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona d\'empremta dactilar"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"S\'està cercant la teva cara…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Icona facial"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacions"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Llanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Càmera en ús"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dades mòbils"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Ús de dades"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dades restants"</string>
@@ -477,7 +470,7 @@
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Es mostra informació sensible durant l\'emissió o la gravació"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"No ho tornis a mostrar"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Esborra-ho tot"</string>
-    <string name="manage_notifications_text" msgid="2386728145475108753">"Gestió"</string>
+    <string name="manage_notifications_text" msgid="2386728145475108753">"Gestiona"</string>
     <string name="notification_section_header_gentle" msgid="4372438504154095677">"Notificacions silencioses"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Esborra totes les notificacions silencioses"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificacions pausades pel mode No molestis"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index b3a8596..916986f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavit metody zadávání"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyzická klávesnice"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Žádná nainstalovaná aplikace s tímto zařízením USB nepracuje. Info. najdete na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Periferní zařízení USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrzeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ověření dokončíte klepnutím na Potvrdit"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Ověřeno"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Použít kód PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Použít gesto"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Použít heslo"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nesprávný kód PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nesprávné gesto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nesprávné heslo"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Příliš mnoho neplatných pokusů.\nZkuste to znovu za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotkněte se snímače otisků prstů"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otisku prstu"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hledáme vás…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Oznámení"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svítilna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparát se používá"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilní data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Využití dat"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Zbývající data"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f0e5898..99fa80e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inputmetoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysisk tastatur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> til håndtering af <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> for at håndtere <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> til håndtering af <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ingen installerede apps fungerer sammen med USB-enheden. Få oplysninger om enheden på <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-ekstraudstyr"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bekræftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tryk på Bekræft for at udføre"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Godkendt"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Brug pinkode"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Brug mønster"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Brug adgangskode"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Forkert pinkode"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Forkert mønster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Forkert adgangskode"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"For mange mislykkede forsøg. \nPrøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sæt fingeren på fingeraftrykslæseren"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon for fingeraftryk"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Forsøger at finde dig…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifikationer"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelygte"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kameraet er i brug"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Dataforbrug"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Resterende data"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f32c577..aced5d7 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Eingabemethoden festlegen"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physische Tastatur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_DEVICE">%2$s</xliff:g> gewähren?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Der App \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" Zugriff auf das Gerät \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\" geben?\nDiese App hat noch nicht die Berechtigung zum Aufnehmen erhalten, könnte jedoch Audio über dieses USB-Gerät aufnehmen."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> gewähren?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Für <xliff:g id="USB_DEVICE">%2$s</xliff:g> <xliff:g id="APPLICATION">%1$s</xliff:g> öffnen?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> öffnen, um <xliff:g id="USB_DEVICE">%2$s</xliff:g> zu bedienen?\nDiese App hat noch keine Berechtigung zum Aufnehmen erhalten, könnte aber Audioaufnahmen über dieses USB-Gerät machen."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Für <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> <xliff:g id="APPLICATION">%1$s</xliff:g> öffnen?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Keine installierten Apps für dieses USB-Zubehör. Weitere Informationen unter <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-Zubehör"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bestätigt"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Zum Abschließen auf \"Bestätigen\" tippen"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authentifiziert"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN verwenden"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Muster verwenden"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Passwort verwenden"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Falsche PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Falsches Muster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Falsches Passwort"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Zu viele Fehlversuche.\nBitte probiere es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden noch einmal."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Berühre den Fingerabdrucksensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerabdruck-Symbol"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Wir suchen nach dir…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Benachrichtigungen"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taschenlampe"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera wird verwendet"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile Daten"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datennutzung"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Verbleibende Daten"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ce693ee..044d396 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Ρύθμιση μεθόδων εισαγωγής"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Φυσικό πληκτρολόγιο"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Να επιτρέπεται η πρόσβαση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> να έχει πρόσβαση στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;\nΔεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Να επιτρέπεται η πρόσβαση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> στο αξεσουάρ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>;"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Να ανοίγει η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> για τη διαχείριση της συσκευής <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Άνοιγμα της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> για τον χειρισμό της συσκευής <xliff:g id="USB_DEVICE">%2$s</xliff:g>;\nΔεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Να ανοίγει η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> για τη διαχείριση του αξεσουάρ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>;"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Δεν έχετε εφαρμογή που να συνεργάζεται με το αξεσουάρ USB. Για περισσότερα: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Αξεσουάρ USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Φωνητική υποβοήθηση"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Ξεκλείδωμα"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Αναμονή για δακτυλικό αποτύπωμα"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ξεκλείδωμα χωρίς τη χρήση του μοναδικού χαρακτηριστικού σας"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ξεκλείδωμα χωρίς τη χρήση του δακτυλικού αποτυπώματός σας"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Σάρωση προσώπου"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Αποστολή"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Διαχείριση ειδοποιήσεων"</string>
@@ -128,21 +128,14 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Επιβεβαιώθηκε"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Πατήστε Επιβεβαίωση για ολοκλήρωση"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Ολοκληρώθηκε ο έλεγχος ταυτότητας"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Χρήση PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Χρήση μοτίβου"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Χρήση κωδικού πρόσβασης"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Εσφαλμένο PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Εσφαλμένο μοτίβο"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Εσφαλμένος κωδικός πρόσβασης"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Πάρα πολλές αποτυχημένες προσπάθειες.\nΔοκιμάστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Αγγίξτε τον αισθητήρα δακτυλικού αποτυπώματος"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Αναζήτηση για εσάς…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Εικονίδιο προσώπου"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ειδοποιήσεις"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Φακός"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Η κάμερα χρησιμοποιείται"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Δεδομένα κινητής τηλεφωνίας"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Χρήση δεδομένων"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Υπολειπόμενα δεδομένα"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 013b4cb..5bf1b0f 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index a21ecb49..a327151 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 013b4cb..5bf1b0f 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 013b4cb..5bf1b0f 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmed"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tap Confirm to complete"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authenticated"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Use PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Use pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Use password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Wrong PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Wrong pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Wrong password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touch the fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingerprint icon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Looking for you…"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index d8cfb30..15617b3 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -50,6 +50,7 @@
     <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎Allow ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to access ‎‏‎‎‏‏‎<xliff:g id="USB_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app has not been granted record permission but could capture audio through this USB device.‎‏‎‎‏‎"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‎Allow ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to access ‎‏‎‎‏‏‎<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‎‎‎‎‏‎Open ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to handle ‎‏‎‎‏‏‎<xliff:g id="USB_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎Open ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to handle ‎‏‎‎‏‏‎<xliff:g id="USB_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app has not been granted record permission but could capture audio through this USB device.‎‏‎‎‏‎"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‎Open ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to handle ‎‏‎‎‏‏‎<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎No installed apps work with this USB accessory. Learn more about this accessory at ‎‏‎‎‏‏‎<xliff:g id="URL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‏‎‎‎USB accessory‎‏‎‎‏‎"</string>
@@ -127,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‎Confirmed‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎Tap Confirm to complete‎‏‎‎‏‎"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎Authenticated‎‏‎‎‏‎"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎Use PIN‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎Use pattern‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎Use password‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‎‎Wrong PIN‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎Wrong pattern‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎Wrong password‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎Too many incorrect attempts.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‎Touch the fingerprint sensor‎‏‎‎‏‎"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎Fingerprint icon‎‏‎‎‏‎"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎Looking for you…‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4b2943c..a69de3b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de intro."</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLa app no tiene permiso para grabar, pero podría capturar audio mediante este dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"¿Deseas abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"¿Quieres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para administrar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLa app no tiene permiso para grabar, pero puede capturar audio mediante este dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"¿Deseas abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ninguna aplic. funciona con este accesorio USB. Más info. acerca de este en <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesorio USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Presiona Confirmar para completarla"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar patrón"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar contraseña"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorrecto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Patrón incorrecto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Contraseña incorrecta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Demasiados intentos incorrectos.\nVuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor de huellas digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícono de huella digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Autenticando tu rostro…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Cámara en uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móviles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 903c50a..f96f7b9 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"¿Quieres que <xliff:g id="APPLICATION">%1$s</xliff:g> pueda acceder a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicación no tiene permisos para grabar, pero podría captar audio a través de este dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"¿Quieres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"¿Quieres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ninguna aplicación instalada funciona con este accesorio USB. Más información: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesorio USB"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toca Confirmar para completar la acción"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Se ha autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar patrón"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar contraseña"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorrecto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Patrón incorrecto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Contraseña incorrecta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Demasiados intentos fallidos.\n Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca el sensor de huellas digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icono de huella digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Buscando tu cara…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Cámara en uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móviles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 113b207..b106a01 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Seadista sisestusmeetodeid"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Füüsiline klaviatuur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Kas lubada rakendusel <xliff:g id="APPLICATION">%1$s</xliff:g> seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g> juurde pääseda?\nSellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Kas avada rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> seadme <xliff:g id="USB_DEVICE">%2$s</xliff:g> kasutamiseks?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Kas avada <xliff:g id="APPLICATION">%1$s</xliff:g>, et käsitseda seadet <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nSellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Kas avada rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> seadme <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> kasutamiseks?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Inst. rak. ei tööta selle USB-seadmega. Lisateavet lisaseadme kohta vt siit: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-lisaseade"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Kinnitatud"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Lõpuleviimiseks puudutage nuppu Kinnita"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenditud"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Kasuta PIN-koodi"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Kasuta mustrit"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Kasuta parooli"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Vale PIN-kood"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Vale muster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Vale parool"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Liiga palju valesid katseid.\nProovige <xliff:g id="NUMBER">%d</xliff:g> sekundi pärast uuesti."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Puudutage sõrmejäljeandurit"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Sõrmejälje ikoon"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Otsitakse teid …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Märguanded"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamp"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kasutusel olev kaamera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiilne andmeside"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Andmeside kasutus"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Järelejäänud andmemaht"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index e541329..4e9fe245 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguratu idazketa-metodoak"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teklatu fisikoa"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> erabiltzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?\nAplikazioak ez du grabatzeko baimenik, baina baliteke USB bidezko gailu horren bidez audioa grabatzea."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_DEVICE">%2$s</xliff:g> kudeatzeko?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_DEVICE">%2$s</xliff:g> erabiltzeko?\nAplikazioak ez du grabatzeko baimenik, baina baliteke audioa grabatzea USB bidezko gailu horren bidez."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> kudeatzeko?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Instalatutako aplikazioek ez dute USB osagarri honekin funtzionatzen. Lortu informazio gehiago osagarriari buruz hemen: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB osagarria"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Berretsita"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Amaitzeko, sakatu \"Berretsi\""</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentifikatuta"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Erabili PIN kodea"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Erabili eredua"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Erabili pasahitza"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN kodea ez da zuzena"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Eredua ez da zuzena"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pasahitza ez da zuzena"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Saiakera oker gehiegi egin dituzu.\nSaiatu berriro <xliff:g id="NUMBER">%d</xliff:g> segundo barru."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sakatu hatz-marken sentsorea"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Hatz-markaren ikonoa"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Zure bila…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Jakinarazpenak"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera abian da"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datu-konexioa"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datuen erabilera"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Geratzen diren datuak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 232f7a2..1751cc9 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"تنظیم روش‌های ورودی"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"صفحه‌کلید فیزیکی"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"به <xliff:g id="APPLICATION">%1$s</xliff:g> برای دسترسی به <xliff:g id="USB_DEVICE">%2$s</xliff:g> اجازه داده شود؟"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏به <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه می‌دهید به <xliff:g id="USB_DEVICE">%2$s</xliff:g>دسترسی داشته باشد؟\nمجوز ضبط به این برنامه داده نشده است اما می‌تواند صدا را ازطریق این دستگاه USB ضبط کند."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"به <xliff:g id="APPLICATION">%1$s</xliff:g> برای دسترسی به <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> اجازه داده شود؟"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"برای استفاده از <xliff:g id="USB_DEVICE">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"‏<xliff:g id="APPLICATION">%1$s</xliff:g> برای رسیدگی به <xliff:g id="USB_DEVICE">%2$s</xliff:g> باز شود؟\nمجوز ضبط به این برنامه داده نشده است اما می‌تواند صدا را ازطریق این دستگاه USB ضبط کند."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"برای استفاده از <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏هیچ برنامه نصب شده‌ای با این وسیله جانبی USB کار نمی‌کند. در <xliff:g id="URL">%1$s</xliff:g> دربارهٔ این وسیله جانبی اطلاعات بیشتری کسب کنید"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏لوازم جانبی USB"</string>
@@ -110,7 +110,7 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"تلفن"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"دستیار صوتی"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"باز کردن قفل"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"در انتظار اثرانگشت"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"در انتظار اثر انگشت"</string>
     <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"باز کردن قفل بدون استفاده از اثر انگشت"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"درحال اسکن کردن چهره"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ارسال"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"تأیید شد"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"برای تکمیل، روی تأیید ضربه بزنید"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"راستی‌آزمایی‌شده"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"استفاده از پین"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"استفاده از الگو"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"استفاده از گذرواژه"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"پین اشتباه است"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"الگو اشتباه است"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"گذرواژه اشتباه است"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"تلاش‌های نادرست بسیاری انجام شده است.\nپس از <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"حسگر اثر انگشت را لمس کنید"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"نماد اثر انگشت"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"درحال جستجوی شما…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"اعلان‌ها"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"چراغ قوه"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"دوربین درحال استفاده"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"داده تلفن همراه"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"مصرف داده"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"داده‌های باقی‌مانده"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 5767c3c..c6c90b3 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Määritä syöttötavat"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyysinen näppäimistö"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> käyttöoikeuden (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> tämän pääsyoikeuden: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nSovellus ei ole saanut tallennuslupaa, mutta voi tallentaa ääntä tämän USB-laitteen avulla."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> käyttöoikeuden (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Avataanko <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_DEVICE">%2$s</xliff:g> voidaan ottaa käyttöön?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Avataanko <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_DEVICE">%2$s</xliff:g> voidaan ottaa käyttöön?\nSovellus ei ole saanut tallennuslupaa, mutta voi tallentaa ääntä tämän USB-laitteen avulla."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Avataanko <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> voidaan ottaa käyttöön?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Asennetut sov. eivät toimi tämän USB-laitteen kanssa. Lisätietoja laitteesta: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-lisälaite"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Vahvistettu"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Valitse lopuksi Vahvista"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Todennettu"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Käytä PIN-koodia"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Käytä kuviota"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Käytä salasanaa"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Väärä PIN-koodi"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Väärä kuvio"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Väärä salasana"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Liian monta virheellistä yritystä.\nYritä uudelleen <xliff:g id="NUMBER">%d</xliff:g> sekunnin kuluttua."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Kosketa sormenjälkitunnistinta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Sormenjälkikuvake"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Etsitään kasvoja…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ilmoitukset"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamppu"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera käytössä"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiilidata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datakäyttö"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Käytettävissä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 04138c0..01427c9 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurer les modes de saisie"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Clavier physique"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Autorisé <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio par l\'intermédiaire de cet appareil USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour gérer <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio par l\'intermédiaire de cet appareil USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aucune application installée compatible avec accessoire USB. En savoir plus sur <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessoire USB"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Toujours ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> lorsque <xliff:g id="USB_DEVICE">%2$s</xliff:g> est connecté"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Toujours ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> lorsque <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> est connecté"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Autoriser le débogage USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte digitale numérique de la clé RSA de l\'ordinateur : \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte numérique de la clé RSA de l\'ordinateur : \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Toujours autoriser sur cet ordinateur"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Autoriser"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Débogage USB non autorisé"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Touchez Confirmer pour terminer"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authentifié"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utiliser un NIP"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utiliser un schéma"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utiliser un mot de passe"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"NIP incorrect"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Schéma incorrect"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Mot de passe incorrect"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Trop de tentatives incorrectes. \nRéessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Touchez le capteur d\'empreintes digitales"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icône d\'empreinte digitale"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Recherche de votre visage…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"L\'appareil photo est en cours d\'utilisation"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Données cellulaires"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilisation de données"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7191426..852bd11 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurer les modes de saisie"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Clavier physique"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio via ce périphérique USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour gérer <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nCette application n\'a pas reçu l\'autorisation d\'enregistrer des contenus audio, mais peut le faire via ce périphérique USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aucune application installée compatible avec accessoire USB. En savoir plus sur <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessoire USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmé"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Appuyez sur \"Confirmer\" pour terminer"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Authentifié"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utiliser un code PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utiliser un schéma"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utiliser un mot de passe"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Code incorrect"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Schéma incorrect"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Mot de passe incorrect"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Trop de tentatives incorrectes.\nVeuillez réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Appuyez sur le lecteur d\'empreinte digitale"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icône d\'empreinte digitale"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Recherche de votre visage…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Caméra en cours d\'utilisation"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Données mobiles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Conso des données"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 4262d88..885302e 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Queres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Queres permitir que a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda ao dispositivo (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nEsta aplicación non está autorizada para realizar gravacións, pero pode capturar audio a través deste dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Queres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Queres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Queres abrir a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> para xestionar o dispositivo (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nEsta aplicación non está autorizada a realizar gravacións, pero pode capturar audio a través deste dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Queres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ningunha aplicación instalada funciona co accesorio USB. Máis información: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesorio USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toca Confirmar para completar o proceso"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar padrón"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar contrasinal"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"O PIN é incorrecto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"O padrón é incorrecto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"O contrasinal é incorrecto"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Realizáronse demasiados intentos incorrectos.\nTéntao de novo en <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toca o sensor de impresión dixital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona de impresión dixital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Buscándote…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacións"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Cámara en uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Datos móbiles"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 66f9a7a..b3ec665 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ઇનપુટ પદ્ધતિઓ સેટ કરો"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ભૌતિક કીબોર્ડ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>ને <xliff:g id="USB_DEVICE">%2$s</xliff:g> ઍક્સેસ કરવાની મંજૂરી આપીએ?\nઆ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફત ઑડિયો કૅપ્ચર કરી શકે છે."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ને હૅન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને ખોલીએ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ને હેન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g> ખોલીએ?\nઆ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફત ઑડિયો કૅપ્ચર કરી શકે છે."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ને હૅન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને ખોલીએ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"કોઈપણ ઇન્સ્ટોલ કરેલી ઍપ્લિકેશનો આ USB ઍક્સેસરી સાથે કામ કરતી નથી. આ ઍક્સેસરી વિશે <xliff:g id="URL">%1$s</xliff:g> પર વધુ જાણો."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ઍક્સેસરી"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"પુષ્ટિ કરી"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"પરીક્ષણ પૂર્ણ કરવા કન્ફર્મ કરોને ટૅપ કરો"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"પ્રમાણિત"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"પિનનો ઉપયોગ કરો"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"પૅટર્નનો ઉપયોગ કરો"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"પાસવર્ડનો ઉપયોગ કરો"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ખોટો પિન"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ખોટી પૅટર્ન"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ખોટો પાસવર્ડ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ઘણા વધારે ખોટા પ્રયત્નો. \n <xliff:g id="NUMBER">%d</xliff:g> સેકંડમાં ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ફિંગરપ્રિન્ટના સેન્સરને સ્પર્શ કરો"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ફિંગરપ્રિન્ટનું આઇકન"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"તમારા માટે શોધી રહ્યાં છે..."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"નોટિફિકેશનો"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ફ્લેશલાઇટ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"કૅમેરાનો ઉપયોગ થાય છે"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"મોબાઇલ ડેટા"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ડેટા વપરાશ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"બાકી ડેટા"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c49cae4..56117ed 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट का तरीका सेट करें"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"सामान्य कीबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> ऐक्सेस करने की अनुमति देना चाहते हैं?\nइस ऐप्लिकेशन को रिकॉर्ड करने की अनुमति नहीं दी गई है. हालांकि, ऐप्लिकेशन इस यूएसबी डिवाइस से ऑडियो कैप्चर कर सकता है."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"इस USB सहायक डिवाइस के साथ कोई भी इंस्टॉल ऐप्स  काम नहीं करता. इस सहायक डिवाइस के बारे में यहां ज़्यादा जानें: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB सहायक साधन"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"पुष्टि हो गई"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"\'पुष्टि करें\' पर टैप करके पूरा करें"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"पुष्टि हो गई"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"पिन इस्तेमाल करें"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"पैटर्न इस्तेमाल करें"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"पासवर्ड इस्तेमाल करें"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"गलत पिन"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"गलत पैटर्न"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"गलत पासवर्ड"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"आपकी कोशिशें बहुत बार गलत हुई हैं.\nआप <xliff:g id="NUMBER">%d</xliff:g> सेकंड में फिर से कोशिश कर सकते हैं."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फ़िंगरप्रिंट सेंसर को छुएं"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फ़िंगरप्रिंट आइकॉन"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"आपको पहचान रहा है…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचनाएं"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ़्लैशलाइट"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"कैमरा इस्तेमाल में है"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"डेटा खर्च"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"शेष डेटा"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 6086764..96b1623 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Postavljanje načina unosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizička tipkovnica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> da pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem tog USB uređaja."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Želite li otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi upravljanja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite li upravljati uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g> putem aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>?\nTa aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem tog USB uređaja."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Želite li otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi upravljanja uređajem <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nijedna instalirana aplikacija ne radi s ovim USB dodatkom. Saznajte više na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB pribor"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrđeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Dodirnite Potvrdi za dovršetak"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentičnost provjerena"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Koristite PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Koristite uzorak"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Koristite zaporku"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Pogrešan PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pogrešan uzorak"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Pogrešna zaporka"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Previše netočnih pokušaja.\nPokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dodirnite senzor otiska prsta"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona otiska prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Tražimo vas…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavijesti"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svjetiljka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Upotrebljava se kamera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilni podaci"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Potrošnja podataka"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostali podaci"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index be039c7..bd23d4d 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Beviteli módok beállítása"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizikai billentyűzet"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Engedélyezi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> számára, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Lehetővé teszi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazásnak, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEz az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Engedélyezi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> számára, hogy hozzáférjen a következőhöz: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást a(z) <xliff:g id="USB_DEVICE">%2$s</xliff:g> kezeléséhez?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást, hogy kezelje a következőt: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEz az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást a(z) <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> kezeléséhez?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"A telepített alkalmazások nem működnek ezzel az USB-kiegészítővel. Bővebben: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-kellék"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Megerősítve"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Koppintson a Megerősítés lehetőségre"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Hitelesítve"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN-kód használata"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Minta használata"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Jelszó használata"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Helytelen PIN-kód"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Helytelen minta"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Helytelen jelszó"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Túl sok helytelen próbálkozás.\nPróbálja újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Érintse meg az ujjlenyomat-érzékelőt"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ujjlenyomat ikonja"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Keresem az Ön arcát…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Értesítések"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zseblámpa"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"A kamera használatban van"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiladatok"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Adathasználat"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Fennmaradó adatmennyiség"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 0f84b50..2647f2f 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Կարգավորել մուտքագրման եղանակները"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Ֆիզիկական ստեղնաշար"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը։"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g>ը։\nՀավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը։"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը մշակելու համար։"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը՝ <xliff:g id="USB_DEVICE">%2$s</xliff:g>ն օգտագործելու համար:\nՀավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը մշակելու համար։"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Այս USB լրասարքի հետ ոչ մի հավելված չի աշխատում: Իմացեք ավելին այս լրասարքի մասին <xliff:g id="URL">%1$s</xliff:g>-ում"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB լրասարք"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Միշտ բացել <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը, երբ <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը միացված է"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Միշտ բացել <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը, երբ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը միացված է"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Թույլատրե՞լ USB-ով վրիպազերծումը"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Համակարգչի RSA-ի բանալի մատնահետքն է`\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"RSA բանալու թվային մատնահետք`\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Միշտ թույլատրել այս համակարգչից"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Թույլատրել"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-ով վրիպազերծումը թույլատրված չէ"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Ձայնային հուշումներ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Ապակողպել"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Մատնահետքի սպասում"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ապակողպել չօգտագործելով մատնահետքը"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Ապակողպել առանց մատնահետքի"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Դեմքի սկանավորում"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Ուղարկել"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Կառավարել ծանուցումները"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Հաստատվեց"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ավարտելու համար հպեք «Հաստատել»"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Նույնականացված է"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Օգտագործել PIN կոդ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Օգտագործել նախշ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Օգտագործել գաղտնաբառ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN կոդը սխալ է"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Նախշը սխալ է"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Գաղտնաբառը սխալ է"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Չափից շատ սխալ փորձ է կատարվել:\nՆորից փորձեք <xliff:g id="NUMBER">%d</xliff:g> վայրկյանից:"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Հպեք մատնահետքի սկաներին"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Մատնահետքի պատկերակ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Դեմքի ճանաչում…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Լապտեր"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Օգտագործվում է տեսախցիկը"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Բջջային ինտերնետ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Տվյալների օգտագործումը"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Մնացած տվյալները"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 0b3ef70..d0b1045 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Menyiapkan metode masukan"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Keyboard fisik"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAplikasi ini belum diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAplikasi ini belum diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Tidak ada apl terpasang yang bekerja dengan aksesori USB ini. Pelajari lebih lanjut tentang aksesori ini di <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Aksesori USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Dikonfirmasi"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ketuk Konfirmasi untuk menyelesaikan"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Diautentikasi"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gunakan PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gunakan pola"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gunakan sandi"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN salah"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Pola salah"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Sandi salah"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Terlalu banyak kesalahan pola.\nCoba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> detik."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sentuh sensor sidik jari"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon sidik jari"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Mencari wajah Anda…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifikasi"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu senter"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera sedang digunakan"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data seluler"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Penggunaan kuota"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Data tersisa"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7a8d290..8985d27 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Setja upp innsláttaraðferðir"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Vélbúnaðarlyklaborð"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nÞetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að sjá um <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að vinna með <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nÞetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að sjá um <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Engin uppsett forrit virka með þessum USB-aukabúnaði. Frekari upplýsingar eru á <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-aukabúnaður"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Staðfest"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ýttu á „Staðfesta“ til að ljúka"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Auðkennt"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Nota PIN-númer"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Nota mynstur"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Nota aðgangsorð"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Rangt PIN-númer"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Rangt mynstur"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Rangt aðgangsorð"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Of margar misheppnaðar tilraunir.\nReyndu aftur eftir <xliff:g id="NUMBER">%d</xliff:g> sekúndur."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Snertu fingrafaralesarann"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Fingrafaratákn"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Leitar að þér ..."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Tilkynningar"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Vasaljós"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Myndavél í notkun"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Farsímagögn"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Gagnanotkun"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Gögn eftir"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index cc053be..68169ab 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura metodi di immissione"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastiera fisica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vuoi consentire all\'app <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nA questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nA questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nessuna app installata funziona con questo accessorio USB. Altre info su <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accessorio USB"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Apri sempre <xliff:g id="APPLICATION">%1$s</xliff:g> quando si collega <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Apri sempre <xliff:g id="APPLICATION">%1$s</xliff:g> quando si collega <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Consentire debug USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Impronta della chiave RSA del computer: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Fingerprint della chiave RSA del computer: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Consenti sempre da questo computer"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Consenti"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Debug USB non consentito"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confermato"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tocca Conferma per completare"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticazione eseguita"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utilizza PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usa sequenza"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utilizza password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN errato"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Sequenza errata"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Password errata"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Troppi tentativi errati.\nRiprova tra <xliff:g id="NUMBER">%d</xliff:g> secondi."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Tocca il sensore di impronte"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icona dell\'impronta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"In attesa del volto…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifiche"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Torcia"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotocamera in uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dati mobili"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilizzo dati"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dati rimanenti"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 09e4f0e..d059489 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"הגדר שיטות קלט"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"מקלדת פיזית"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"האם לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏האם לאפשר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nאפליקציה זו לא קיבלה הרשאה להקליט אך יכולה לתעד אודיו באמצעות מכשיר USB זה."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"האם לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"האם לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> כדי לעבוד עם <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"האם לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> כדי לעבוד עם <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏אין אפליקציות מותקנות הפועלות עם אביזר ה-USB. למידע נוסף על אביזר זה היכנס לכתובת <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏אביזר USB"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"מאושר"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"יש להקיש על \'אישור\' לסיום"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"מאומת"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"שימוש בקוד אימות"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"שימוש בקו ביטול נעילה"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"שימוש בסיסמה"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"קוד אימות שגוי"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"קו ביטול נעילה שגוי"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"סיסמה שגויה"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"יותר מדי ניסיונות שגויים.\nיש לנסות שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"יש לגעת בחיישן טביעות האצבע"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"סמל טביעת אצבע"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"מחפש אותך…"</string>
@@ -384,8 +378,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"התראות"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"פנס"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"מצלמה בשימוש"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"חבילת גלישה"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"שימוש בנתונים"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"מכסת נתונים נותרת"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 3dc9fb7..e89ae5b 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"入力方法をセットアップ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"物理キーボード"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g> へのアクセスを許可しますか?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g>へのアクセスを許可しますか?\nこのアプリに録音権限は付与されていませんが、アクセスを許可すると、この USB デバイスから音声を収集できるようになります。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> へのアクセスを許可しますか?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> を起動して <xliff:g id="USB_DEVICE">%2$s</xliff:g> を処理しますか?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> を開いて <xliff:g id="USB_DEVICE">%2$s</xliff:g>を利用しますか?\nこのアプリに録音権限は付与されていませんが、この USB デバイスから音声を収集できるようになります。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> を起動して <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> を処理しますか?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"このUSBアクセサリを扱うアプリはインストールされていません。詳細: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USBアクセサリ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"確認しました"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"完了するには [確認] をタップしてください"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"認証済み"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN を使用"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"パターンを使用"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"パスワードを使用"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN が正しくありません"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"パターンが正しくありません"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"パスワードが正しくありません"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"間違えた回数が上限を超えました。\n<xliff:g id="NUMBER">%d</xliff:g> 秒後にもう一度お試しください。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"指紋認証センサーをタップしてください"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋アイコン"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"顔を認証しています…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ライト"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"カメラを使用中"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"モバイルデータ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"データ使用量"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"残りのデータ"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 24db256..50006dd 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"შეყვანის მეთოდების დაყენება"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ფიზიკური კლავიატურა"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"მიეცეს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის უფლება?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"დართავთ <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის ნებას?\nამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"მიეცეს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-ზე წვდომის უფლება?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"გსურთ, გახსნათ <xliff:g id="APPLICATION">%1$s</xliff:g>, <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ის გამოსაყენებლად?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"გახსნით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ის გამოსაყენებლად?\nამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"გსურთ, გახსნათ <xliff:g id="APPLICATION">%1$s</xliff:g>, <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-ის გამოსაყენებლად?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"არცერთი დაყენებული აპი არ მუშაობს ამ USB აქსესუართან. შეიტყვეთ მეტი ამ აქსესუარის შესახებ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB აქსესუარი"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"დადასტურებული"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"დასასრულებლად შეეხეთ „დადასტურებას“"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ავტორიზებულია"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN-კოდის გამოყენება"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ნიმუშის გამოყენება"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"პაროლის გამოყენება"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN-კოდი არასწორია"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ნიმუში არასწორია"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"პაროლი არასწორია"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"დაფიქსირდა ძალიან ბევრი არასწორი მცდელობა.\nცადეთ ხელახლა <xliff:g id="NUMBER">%d</xliff:g> წამში."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"შეეხეთ თითის ანაბეჭდის სენსორს"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"თითის ანაბეჭდის ხატულა"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"მიმდინარეობს თქვენი ძიება…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"შეტყობინებები"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ფანარი"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"კამერა გამოიყენება"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"მობილური ინტერნეტი"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"მონაცემთა მოხმარება"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"დარჩენილი მონაცემები"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index ff1b9fc..05e521c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Енгізу әдістерін орнату"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физикалық пернетақта"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысына кіруге рұқсат берілсін бе?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын пайдалануға рұқсат етілсін бе?\nҚолданбаның жазу рұқсаты жоқ, бірақ осы USB құрылғысы арқылы аудио жаза алады."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> жабдығына кіруге рұқсат берілсін бе?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> жабдығын басқару үшін <xliff:g id="APPLICATION">%1$s</xliff:g> ашылсын ба?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын пайдалану үшін <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасын ашу керек пе?\nҚолданбаға жазу рұқсаты берілмеді, бірақ ол осы USB құрылғысы арқылы дыбыс жаза алады."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> жабдығын басқару үшін <xliff:g id="APPLICATION">%1$s</xliff:g> ашылсын ба?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Орнатылған қолданбалар осы USB жабдығымен жұмыс жасамайды.Жабдықты <xliff:g id="URL">%1$s</xliff:g> ден қараңыз."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB жабдығы"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Расталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Аяқтау үшін \"Растау\" түймесін түртіңіз."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Аутентификацияланған"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN кодын пайдалану"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Өрнекті пайдалану"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Құпия сөзді пайдалану"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN коды қате."</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Өрнек қате."</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Құпия сөз қате."</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Тым көп қате енгізілді.\n<xliff:g id="NUMBER">%d</xliff:g> секундта әрекетті қайталаңыз."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Саусақ ізін оқу сканерін түртіңіз"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Саусақ ізі белгішесі"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Бет ізделуде…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Хабарландырулар"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Қалта шам"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камера қолданылып жатыр"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобильдік деректер"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Дерек шығыны"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Қалған деректер"</string>
@@ -856,7 +848,7 @@
     <string name="pip_phone_settings" msgid="8080777499521528521">"Реттеулер"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Жабу үшін төмен қарай сүйреңіз"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Mәзір"</string>
-    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> \"сурет ішіндегі сурет\" режимінде"</string>
+    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> \"суреттегі сурет\" режимінде"</string>
     <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл мүмкіндікті пайдалануын қаламасаңыз, параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string>
     <string name="pip_play" msgid="1417176722760265888">"Ойнату"</string>
     <string name="pip_pause" msgid="8881063404466476571">"Кідірту"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 323138c..a628383 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"រៀបចំ​វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ក្ដារ​ចុច​ពិតប្រាកដ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"អនុញ្ញាត <xliff:g id="APPLICATION">%1$s</xliff:g> ឱ្យចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g> មែនទេ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"អនុញ្ញាតឱ្យ <xliff:g id="APPLICATION">%1$s</xliff:g> ចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nកម្មវិធីនេះ​មិនទាន់បាន​ទទួលសិទ្ធិ​ថតសំឡេងនៅឡើយទេ ប៉ុន្តែ​អាចថត​សំឡេង​តាមរយៈ​ឧបករណ៍ USB នេះបាន។"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"អនុញ្ញាត <xliff:g id="APPLICATION">%1$s</xliff:g> ឱ្យចូលប្រើ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> មែនទេ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_DEVICE">%2$s</xliff:g> មែនទេ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nកម្មវិធីនេះ​មិនទាន់បាន​ទទួលសិទ្ធិ​ថតសំឡេង​នៅឡើយទេ ប៉ុន្តែអាច​ថតសំឡេង​តាមរយៈ​ឧបករណ៍ USB នេះ។"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> មែនទេ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"គ្មាន​កម្មវិធី​បាន​ដំឡើង​ដំណើរការ​ជា​មួយ​ឧបករណ៍​យូអេសប៊ី។ ស្វែងយល់​បន្ថែម​អំពី​ឧបករណ៍​នេះ​នៅ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ឧបករណ៍​យូអេសប៊ី"</string>
@@ -128,22 +128,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"បានបញ្ជាក់"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ចុច \"បញ្ជាក់\" ដើម្បីបញ្ចប់"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"បាន​ផ្ទៀងផ្ទាត់"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ប្រើកូដ PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ប្រើ​លំនាំ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ប្រើពាក្យសម្ងាត់"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"កូដ PIN មិន​ត្រឹមត្រូវ​"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"លំនាំមិនត្រឹមត្រូវ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ពាក្យសម្ងាត់មិនត្រឹមត្រូវ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ការព្យាយាម​ចូលខុស​ច្រើនដងពេក។\nសូមព្យាយាម​ម្តងទៀត​ក្នុងរយៈពេល <xliff:g id="NUMBER">%d</xliff:g> វិនាទី។"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ប៉ះ​ឧបករណ៍​ចាប់ស្នាម​ម្រាមដៃ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"រូបតំណាង​ស្នាម​ម្រាមដៃ"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"រូប​ស្នាម​ម្រាមដៃ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"កំពុងស្វែងរកអ្នក…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"រូប​ផ្ទៃមុខ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុង​ពង្រីក​ត្រូវ​គ្នា។"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ការ​ជូនដំណឹង"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ពិល"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"កំពុងប្រើ​កាមេរ៉ា"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ការ​ប្រើ​ទិន្នន័យ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ទិន្នន័យ​នៅសល់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index ac593e8..dc4674a 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ಇನ್‌ಪುಟ್ ವಿಧಾನಗಳನ್ನು ಹೊಂದಿಸು"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?\nಈ ಆ್ಯಪ್‌ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಗೆ ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿಯಂತ್ರಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?\nಈ ಆ್ಯಪ್‌ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ಆಪ್‌ಗಳು USB ಪರಿಕರದಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ. ಆ ಬಗ್ಗೆ <xliff:g id="URL">%1$s</xliff:g> ನಲ್ಲಿ ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ಪರಿಕರ"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"ಕಂಪ್ಯೂಟರ್‌ನ RSA ಕೀ ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಹೀಗಿದೆ :\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"ಕಂಪ್ಯೂಟರ್‌ನ RSA ಕೀ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಹೀಗಿದೆ :\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"ಈ ಕಂಪ್ಯೂಟರ್‌ನಿಂದ ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ಅನುಮತಿಸಿ"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸಲಾಗಿಲ್ಲ"</string>
@@ -110,8 +110,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ಫೋನ್"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"ಅನ್‌ಲಾಕ್"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ನಿಮ್ಮ ಬೆರಳಚ್ಚು ಬಳಸದೆಯೇ ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‍‍ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ನಿಮ್ಮ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸದೆಯೇ ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"ಮುಖವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ಕಳುಹಿಸಿ"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ಪೂರ್ಣಗೊಳಿಸಲು ದೃಢೀಕರಿಸಿ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ದೃಢೀಕರಿಸಲಾಗಿದೆ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ಪಿನ್ ಬಳಸಿ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ಪ್ಯಾಟರ್ನ್ ಬಳಸಿ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ಪಾಸ್‌ವರ್ಡ್ ಬಳಸಿ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ತಪ್ಪಾದ ಪಿನ್‌"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ಪಾಸ್‌ವರ್ಡ್ ತಪ್ಪಾಗಿದೆ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ಹಲವಾರು ತಪ್ಪು ಪ್ರಯತ್ನಗಳು.\nಮತ್ತೆ <xliff:g id="NUMBER">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌‌ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ನಿಮಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ಫ್ಲಾಶ್‌ಲೈಟ್‌"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ಕ್ಯಾಮರಾ ಬಳಕೆಯಲ್ಲಿದೆ"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ಡೇಟಾ ಬಳಕೆ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ಉಳಿದಿರುವ ಡೇಟಾ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f37ec00..714af0c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"입력 방법 설정"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"물리적 키보드"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>에서 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?\n이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 열어 <xliff:g id="USB_DEVICE">%2$s</xliff:g>을(를) 처리하시겠습니까?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>을(를) 처리하기 위해 <xliff:g id="APPLICATION">%1$s</xliff:g>을(를) 여시겠습니까?\n이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 열어 <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>을(를) 처리하시겠습니까?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"이 USB와 호환되는 설치 앱이 없습니다. <xliff:g id="URL">%1$s</xliff:g>에서 세부정보를 참조하세요."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB 액세서리"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"음성 지원"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"잠금 해제"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"지문 대기 중"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"지문 파일을 사용하지 않고 잠금 해제"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"지문을 사용하지 않고 잠금 해제"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"얼굴 스캔 중"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"보내기"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"알림 관리"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"확인함"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"완료하려면 확인을 탭하세요."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"인증됨"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN 사용"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"패턴 사용"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"비밀번호 사용"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"잘못된 PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"잘못된 패턴"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"잘못된 비밀번호"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"잘못된 시도 횟수가 너무 많습니다.\n<xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 시도하세요."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"지문 센서를 터치하세요."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"지문 아이콘"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"찾는 중..."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"알림"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"손전등"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"카메라 사용 중"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"모바일 데이터"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"데이터 사용"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"잔여 데이터"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index beb2b02..820c6b3 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Киргизүү ыкмасын тууралоо"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Аппараттык тергич"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүн колдоно берсинби?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу үчүн <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүнө мүмкүнчүлүк алууга уруксат бересизби?\nБул колдонмонун жаздырууга уруксаты жок, бирок бул USB түзмөгү аркылуу аудиону жаздыра алат."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> кабелин колдоно берсинби?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүнө туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу ачылсынбы?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> кабелине туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> ачылсынбы?\nБул колдонмонун жаздырууга уруксаты жок, бирок бул USB түзмөгү аркылуу аудиону жаздыра алат."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> кабелине туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу ачылсынбы?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Эч бир орнотулган колдонмо USB аксессуар м-н иштебейт. Кенен маалыматтар: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB шайманы"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Ырасталды"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Бүтүрүү үчүн \"Ырастоо\" баскычын басыңыз"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Аныктыгы текшерилди"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN кодду колдонуу"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Графикалык ачкычты колдонуу"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Сырсөз колдонуу"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN код туура эмес"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Графикалык ачкыч туура эмес"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Сырсөз туура эмес"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Өтө көп жолу туура эмес аракет кылынды.\n<xliff:g id="NUMBER">%d</xliff:g> секунддан кийин кайра кайталаңыз."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Манжа изинин сенсорун басыңыз"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Манжа изинин сүрөтчөсү"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Жүзүңүз изделүүдө…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Билдирмелер"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Кол чырак"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камера колдонулууда"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилдик Интернет"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Дайындардын өткөрүлүшү"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Калган дайындар"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 68c9951..89d3779 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ຕັ້ງຄ່າວິທີການປ້ອນຂໍ້ມູນ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ແປ້ນພິມແທ້"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?\nແອັບນີ້ບໍ່ໄດ້ຮັບອະນຸາດໃຫ້ບັນທຶກໄດ້ແຕ່ສາມາດບັນທຶກສຽງໄດ້ຜ່ານອຸປະກອນ USB ນີ້."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ໄດ້ບໍ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ກັບ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ບໍ?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ບໍ?\nແອັບນີ້ຍັງບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ບັນທຶກເທື່ອ ແຕ່ສາມາດບັນທຶກສຽງຜ່ານອຸປະກອນ USB ນີ້ໄດ້."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ກັບ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ບໍ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ບໍ່ມີແອັບຯໃດທີ່ຕິດຕັ້ງໄປແລ້ວ ສາມາດເຮັດວຽກຮ່ວມກັບອຸປະກອນເສີມ USB ນີ້ໄດ້. ສຶກສາເພີ່ມເຕີມກ່ຽວກັບອຸປະກອນເສີມນີ້ທີ່ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ອຸປະກອນເສີມ USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ຢືນຢັນແລ້ວ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ແຕະຢືນຢັນເພື່ອສຳເລັດ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ຮັບຮອງຄວາມຖືກຕ້ອງແລ້ວ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ໃຊ້ PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ໃຊ້ຮູບແບບ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ໃຊ້ລະຫັດຜ່ານ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN ບໍ່ຖືກຕ້ອງ"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ຮູບແບບບໍ່ຖືກຕ້ອງ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ມີ​ຄວາມ​ພະ​ຍາ​ຍາມ​ບໍ່​ຖືກ​ຕ້ອງ​ຫຼາຍ​ເທື່ອ​ເກີນ​ໄປ.\nກະລຸນາລອງ​ໃໝ່​ອີກ​ໃນ <xliff:g id="NUMBER">%d</xliff:g> ​ວິ​ນາ​ທີ."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມື"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ໄອຄອນລາຍນິ້ວມື"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ກຳລັງຊອກຫາທ່ານ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ການແຈ້ງເຕືອນ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"​ໄຟ​ສາຍ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ມີການໃຊ້ກ້ອງຖ່າຍຮູບຢູ່"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ອິນເຕີເນັດມືຖື"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"​ການ​​ນຳ​ໃຊ້​​ຂໍ້​ມູນ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"​ຂໍ້​ມູນ​ທີ່​ຍັງ​ເຫຼືອ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 230194d..208f49b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nustatyti įvesties metodus"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizinė klaviatūra"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nŠiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Atidaryti „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad būtų galima tvarkyti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Atidaryti programą „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad ji galėtų tvarkyti „<xliff:g id="USB_DEVICE">%2$s</xliff:g>“?\nŠiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Atidaryti „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad būtų galima tvarkyti įrenginį (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Su šiuo USB priedu neveiks jokios įdieg. pr. Suž. daugiau apie šį priedą adresu <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB reikmuo"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Patvirtinta"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Paliesk. „Patvirtinti“, kad užbaigtumėte"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentifikuota"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Naudoti PIN kodą"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Naudoti atrakinimo piešinį"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Naudoti slaptažodį"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Netinkamas PIN kodas"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Netinkamas atrakinimo piešinys"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Netinkamas slaptažodis"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Per daug klaidingų bandymų.\nBandykite dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Palieskite piršto antspaudo jutiklį"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Piršto antspaudo piktograma"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ieškoma jūsų…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pranešimai"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Žibintuvėlis"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparatas naudojamas"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiliojo ryšio duomenys"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Duomenų naudojimas"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Likę duomenys"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e1905f5..a96fc3b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Iestatīt ievades metodes"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziskā tastatūra"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šai ierīcei: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt ierīcei “<xliff:g id="USB_DEVICE">%2$s</xliff:g>”?\nŠai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šim piederumam: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vai atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai izmantotu šo ierīci: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vai vēlaties atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai pārvaldītu ierīci <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nŠai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vai atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai izmantotu šo piederumu: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Neviena no inst. liet. nedarb. ar šo USB pied. Uzz. vairāk par šo pied. vietnē <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB piederums"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Apstiprināts"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Lai pabeigtu, pieskarieties Apstiprināt"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentifikācija veikta"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Izmantot PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Izmantot kombināciju"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Izmantot paroli"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nepareizs PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nepareiza kombinācija"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nepareiza parole"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Pārāk daudz neveiksmīgu mēģinājumu.\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundēm."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Pieskarieties pirksta nospieduma sensoram"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Pirksta nospieduma ikona"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Notiek jūsu sejas meklēšana…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Paziņojumi"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zibspuldze"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera tiek lietota"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilie dati"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datu lietojums"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Atlikušie dati"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 300dff5..f8dea79 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Постави методи на внес."</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физичка тастатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Дали дозволувате <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапи до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Да се отвори <xliff:g id="APPLICATION">%1$s</xliff:g> за да управува со <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Да се отвори ли <xliff:g id="APPLICATION">%1$s</xliff:g> за да се управува со <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Да се отвори <xliff:g id="APPLICATION">%1$s</xliff:g> за да управува со <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Нема инсталирано апликации што работат со овој USB додаток. Дознајте повеќе за овој додаток на <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB додаток"</string>
@@ -128,22 +128,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Потврдено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Допрете „Потврди“ за да се заврши"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Проверена"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Користи PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Користи шема"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Користи лозинка"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Погрешен PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Погрешна шема"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Погрешна лозинка"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Премногу погрешни обиди.\nОбидете се повторно за <xliff:g id="NUMBER">%d</xliff:g>секунди."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Допрете го сензорот за отпечатоци"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечатоци"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона за отпечаток"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ве бараме вас…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Икона за лице"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Копче за компатибилност на зум."</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известувања"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Светилка"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камерата е во употреба"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилен интернет"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Потрошен интернет"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Преостанати податоци"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 0a06b2c..66265cb 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ടൈപ്പുചെയ്യൽ രീതികൾ സജ്ജീകരിക്കുക"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ഫിസിക്കൽ കീബോഡ്"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്‌സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്‌സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കണോ?\nഈ ആപ്പിന് റെക്കോർഡ് അനുമതി നൽകിയിട്ടില്ല, എന്നാൽ ഈ USB ഉപകരണത്തിലൂടെ ഓഡിയോ ക്യാപ്‌ചർ ചെയ്യാനാവും."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ആക്‌സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> കൈകാര്യം ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> തുറക്കണോ?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> കൈകാര്യം ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> തുറക്കണോ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ഈ USB ആക്‌സസ്സറിയിൽ ഇൻസ്‌റ്റാളുചെയ്‌തവയൊന്നും പ്രവർത്തിക്കുന്നില്ല. <xliff:g id="URL">%1$s</xliff:g>-ൽ ഇതേക്കുറിച്ച് കൂടുതലറിയുക"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ആക്‌സസ്സറി"</string>
@@ -110,7 +111,7 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ഫോണ്‍"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"വോയ്‌സ് സഹായം"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"അണ്‍ലോക്ക് ചെയ്യുക"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ഫിംഗർപ്രിന്റിനായി കാക്കുന്നു"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ഫിംഗർപ്രിന്റിനായി കാത്തിരിക്കുന്നു"</string>
     <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കാതെ അൺലോക്കുചെയ്യുക"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"മുഖം സ്കാൻ ചെയ്യുന്നു"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"അയയ്ക്കുക"</string>
@@ -128,22 +129,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"സ്ഥിരീകരിച്ചു"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"പൂർത്തിയാക്കാൻ സ്ഥിരീകരിക്കുക ടാപ്പ് ചെയ്യൂ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"പരിശോധിച്ചുറപ്പിച്ചു"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"വിരലടയാള സെൻസർ സ്‌പർശിക്കുക"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"വിരലടയാള ഐക്കൺ"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"പിൻ ഉപയോഗിക്കുക"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"പാറ്റേൺ ഉപയോഗിക്കുക"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"പാസ്‌വേഡ് ഉപയോഗിക്കുക"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"പിൻ തെറ്റാണ്"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"പാറ്റേൺ തെറ്റാണ്"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"പാസ്‌വേഡ് തെറ്റാണ്"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"നിരവധി തെറ്റായ ശ്രമങ്ങൾ. \n<xliff:g id="NUMBER">%d</xliff:g> സെക്കൻഡിൽ വീണ്ടും ശ്രമിക്കുക."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ഫിംഗർപ്രിന്റ് സെൻസർ സ്‌പർശിക്കുക"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"നിങ്ങൾക്കായി തിരയുന്നു…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"മുഖത്തിന്റെ ഐക്കൺ"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"അനുയോജ്യതാ സൂം ബട്ടൺ."</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"അറിയിപ്പുകൾ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ടോർച്ച്"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ക്യാമറ ഉപയോഗത്തിലാണ്"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"മൊബൈൽ ഡാറ്റ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ഡാറ്റാ ഉപയോഗം"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ശേഷിക്കുന്ന ഡാറ്റ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 0298d20..00e6dcb 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Оруулах аргыг тохируулах"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Бодит гар"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g>-д <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?\nЭнэ аппад бичих зөвшөөрөл олгогдоогүй ч USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?\nЭнэ апликейшнд бичих зөвшөөрөл олгогдоогүй ч энэ USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Энэ USB хэрэгсэл дээр суулгасан апп ажиллаагүй байна. Энэ хэрэгслийн талаар <xliff:g id="URL">%1$s</xliff:g>-с дэлгэрэнгүй үзнэ үү."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB төхөөрөмж"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Баталгаажсан"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Дуусгахын тулд баталгаажуулахыг товших"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Баталгаажуулагдсан"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ПИН ашиглах"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Хээ ашиглах"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Нууц үг ашиглах"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ПИН код буруу байна"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Хээ буруу байна"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Нууц үг буруу байна"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Хэт олон удаа буруу оруулсан байна.\n<xliff:g id="NUMBER">%d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Хурууны хээ мэдрэгчид хүрэх"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Хурууны хээний дүрс тэмдэг"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Таныг хайж байна…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Мэдэгдэл"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Гар чийдэн"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Камерыг ашиглаж байна"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобайл дата"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Дата ашиглалт"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Үлдсэн дата"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 07b985f..671060b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट पद्धती सेट करा"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"वास्तविक कीबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अ‍ॅक्सेस करण्याची अनुमती द्यायची का?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अ‍ॅक्सेस करण्याची अनुमती द्यायची का?\nया अ‍ॅपला रेकॉर्ड करण्याची परवानगी दिलेली नाही पण या USB डिव्हाइसद्वारे ऑडिओ कॅप्चर केला जाऊ शकतो."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> अ‍ॅक्सेस करण्याची अनुमती द्यायची का?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> हाताळण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे का?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> हाताळण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे का?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"इंस्टॉल केलेली अ‍ॅप्स या USB उपसाधनासह कार्य करत नाहीत. <xliff:g id="URL">%1$s</xliff:g> येथे या उपसाधनाविषयी अधिक जाणून घ्या"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB उपसाधन"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"निश्चित केले"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"पूर्ण करण्यासाठी खात्री करा वर टॅप करा"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ऑथेंटिकेशन केलेले"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"पिन वापरा"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"पॅटर्न वापरा"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"पासवर्ड वापरा"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"चुकीचा पिन"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"चुकीचा पॅटर्न"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"चुकीचा पासवर्ड"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"बरेच चुकीचे प्रयत्न. \n <xliff:g id="NUMBER">%d</xliff:g> सेकंदांमध्‍ये पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फिंगरप्रिंट सेन्सरला स्पर्श करा"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फिंगरप्रिंट आयकन"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"तुमच्यासाठी शोधत आहे…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचना"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ्लॅशलाइट"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"कॅमेरा वापरात आहे"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"डेटा वापर"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"शिल्लक डेटा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index f696ee3..265f161 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Sediakan kaedah input"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Papan kekunci fizikal"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nApl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nApl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Tiada apl yg dipsg bfungsi dgn aksesori USB ini. Ketahui lg ttg aksesori ini di <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Aksesori USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Disahkan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Ketik Sahkan untuk menyelesaikan"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Disahkan"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gunakan PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gunakan corak"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gunakan kata laluan"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN salah"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Corak salah"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Kata laluan salah"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Terlalu banyak percubaan yang salah.\nCuba lagi dalam masa <xliff:g id="NUMBER">%d</xliff:g> saat."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Sentuh penderia cap jari"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon cap jari"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Mencari anda…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu suluh"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera sedang digunakan"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data mudah alih"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Penggunaan data"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Baki data"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index eb73df7..c06bb8c 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ထည့်သွင်းနည်းများ သတ်မှတ်ခြင်း"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ခလုတ်ပါဝင်သော ကီးဘုတ်"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> အား ဝင်သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ခွင့်ပြုပါသလား။"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> အား <xliff:g id="USB_DEVICE">%2$s</xliff:g> ကို သုံးခွင့်ပြုမလား။\nဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> အား ဝင်သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ခွင့်ပြုပါသလား။"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ဆောင်ရွက်ရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်လိုပါသလား။"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ကို သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်မလား။\nဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ဆောင်ရွက်ရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်လိုပါသလား။"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ဒီUSBပစ္စည်းနှင့်ဘယ်အပ်ပလီကေးရှင်းမှ အလုပ်မလုပ်ပါ။ ပိုမိုသိရန် <xliff:g id="URL">%1$s</xliff:g>တွင် လေ့လာပါ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USBတွဲဖက်ပစ္စည်းများ"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ချိတ်ဆက်သည့်အခါ <xliff:g id="APPLICATION">%1$s</xliff:g> ကို အမြဲဖွင့်ပါ"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ချိတ်ဆက်သည့်အခါ <xliff:g id="APPLICATION">%1$s</xliff:g> ကို အမြဲဖွင့်ပါ"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB အမှားရှာဖွေပြင်ဆင်ခြင်း ခွင့်ပြုပါမည်လား?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"ဒီကွန်ပျူတာရဲ့ RSA key fingerprint ကတော့:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g> ဖြစ်ပါသည်"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"ဤကွန်ပျူတာ၏ RSA သော့လက်ဗွေ-\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"ဒီကွန်ပျူတာမှ အမြဲခွင့်ပြုရန်"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ခွင့်ပြုရန်"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB အမှားပြင်ဆင်ခြင်း ခွင့်မပြုပါ"</string>
@@ -110,8 +110,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ဖုန်း"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"အသံ အကူအညီ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"သော့ဖွင့်ရန်"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"လက်ဗွေရာကို စောင့်နေပါသည်"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"လက်ဗွေရာ မသုံးဘဲ ဖွင့်ပါ"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"လက်ဗွေကို စောင့်နေသည်"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"လက်ဗွေ မသုံးဘဲ ဖွင့်ပါ"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"မျက်နှာ စကင်ဖတ်နေသည်"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ပို့ရန်"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"အကြောင်းကြားချက်များကို စီမံရန်"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"အတည်ပြုပြီးပြီ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"အပြီးသတ်ရန်အတွက် \'အတည်ပြုရန်\' ကို တို့ပါ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"အထောက်အထားစိစစ်ပြီးပြီ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ပင်နံပါတ်သုံးရန်"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ပုံစံကို သုံးရန်"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"စကားဝှက် သုံးရန်"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ပင်နံပါတ် မှားနေသည်"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ပုံစံ မှားနေသည်"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"စကားဝှက် မှားနေသည်"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"မှားသည့် အကြိမ် အရေအတွက် အလွန်များသည်။\n<xliff:g id="NUMBER">%d</xliff:g>စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"လက်ဗွေအာရုံခံကိရိယာကို တို့ပါ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"လက်ဗွေ သင်္ကေတ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"သင့်ကို ရှာဖွေနေသည်…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"အကြောင်းကြားချက်များ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ဖလက်ရှ်မီး"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ကင်မရာကို သုံးနေသည်"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"မိုဘိုင်းဒေတာ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ဒေတာ သုံးစွဲမှု"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ကျန်ရှိ ဒေတာ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9e1c5db..c213b10 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inndatametoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysisk tastatur"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å behandle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å håndtere <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å behandle <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Ingen installerte apper støtter dette USB-tilbehøret. Les mer om tilbehøret på <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-enhet"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bekreftet"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Trykk på Bekreft for å fullføre"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentisert"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Bruk PIN-kode"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Bruk mønster"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Bruk passord"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Feil PIN-kode"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Feil mønster"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Feil passord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"For mange ugyldige forsøk.\nPrøv på nytt om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Trykk på fingeravtrykkssensoren"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon for fingeravtrykk"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Ser etter deg …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Varsler"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelykt"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kameraet er i bruk"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Databruk"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Gjenværende data"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5a00002..8006279 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट विधिहरू सेटअप गर्नुहोस्"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"वास्तविक किबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्न अनुमति दिने हो?\nयो अनुप्रयोगलाई रेकर्ड गर्ने अनुमति प्रदान गरिएको छैन तर यसले USB यन्त्रमार्फत अडियो क्याप्चर गर्न सक्छ।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> को व्यवस्थापन गर्न <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्ने हो?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> को व्यवस्थापन गर्न <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्ने हो?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"यस USB उपकरणसँग स्थापित अनुप्रयोग काम गर्दैन। यस उपकरणको बारेमा <xliff:g id="URL">%1$s</xliff:g> मा धेरै जान्नुहोस्"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB सहयोगी"</string>
@@ -58,7 +59,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> जडान भएको बेला सधैँ <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्नुहोस्"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> जडान भएको बेला सधैँ <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्नुहोस्"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB डिबग गर्नको लागि अनुमति दिने हो?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"कम्प्युटरको RSA कुञ्जी औंलाछाप:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"कम्प्युटरको RSA कुञ्जीको फिंगरप्रिन्ट:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"यो कम्प्युटरबाट सधैँ अनुमति दिनुहोस्"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"अनुमति दिनुहोस्"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB डिबग गर्न अनुमति छैन"</string>
@@ -111,7 +112,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"आवाज सहायता"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"खोल्नुहोस्"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"फिंगरप्रिन्ट कुर्दै"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"तपाईँको फिंगरप्रिन्ट बिना नै अनलक गर्नुहोस्"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"आफ्नो फिंगरप्रिन्ट बिना नै अनलक गर्नुहोस्"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"अनुहार स्क्यान गर्दै"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"पठाउनुहोस्"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"सूचनाहरू व्यवस्थित गर्नुहोस्"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"पुष्टि भयो"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"पूरा गर्नका लागि पुष्टि गर्नुहोस् नामक विकल्पमा ट्याप गर्नुहोस्"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"प्रमाणीकरण गरियो"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN प्रयोग गर्नुहोस्"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ढाँचा प्रयोग गर्नुहोस्"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"पासवर्ड प्रयोग गर्नुहोस्"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN मिलेन"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ढाँचा मिलेन"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"पासवर्ड मिलेन"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"अत्यन्तै धेरै पटक गलत प्रयास गरिए। \n <xliff:g id="NUMBER">%d</xliff:g>सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"फिंगरप्रिन्ट सेन्सरमा छुनुहोस्‌"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"फिंगरप्रिन्ट जनाउने आइकन"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"तपाईंलाई खोज्दै…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"अधिसूचनाहरू"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ्ल्यासलाइट"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"क्यामेरा प्रयोगमा छ"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"मोबाइल डेटा"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"डेटाको प्रयोग"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"बाँकी डेटा"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index dacbd53..61e4c33 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Invoermethoden instellen"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysiek toetsenbord"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDeze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te verwerken?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te verwerken?\nDeze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> te verwerken?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Er werken geen geïnstalleerde apps met dit USB-accessoire. Meer informatie op: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-accessoire"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bevestigd"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tik op Bevestigen om te voltooien"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Geverifieerd"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Pincode gebruiken"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Patroon gebruiken"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Wachtwoord gebruiken"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Onjuiste pincode"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Onjuist patroon"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Onjuist wachtwoord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Te veel onjuiste pogingen.\nProbeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Raak de vingerafdruksensor aan"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Vingerafdrukpictogram"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Jouw gezicht zoeken…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Meldingen"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zaklamp"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Camera in gebruik"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobiele data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datagebruik"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Resterende gegevens"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 2720abf..527d69f 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ଇନପୁଟ୍‍ ପଦ୍ଧତି ସେଟ୍‍ କରନ୍ତୁ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ଫିଜିକଲ୍ କୀ’ବୋର୍ଡ୍"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍‍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ କି?\nଏହି ଆପ୍‌କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍ଟର୍ କରିପାରିବ।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ଆକ୍ସେସ୍‍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ନିୟନ୍ତ୍ରଣ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g> ଖୋଲିବେ?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ନିୟନ୍ତ୍ରଣ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g> ଖୋଲିବେ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ଇନଷ୍ଟଲ୍‍ ହୋଇଥିବା କୌଣସି ଆପ୍‍ ଏହି USB ଆକ୍ସେସୋରୀରେ କାମ କରେନାହିଁ। ଏହି ଆକ୍ସେସୋରୀ ବିଷୟରେ <xliff:g id="URL">%1$s</xliff:g>ରେ ଅଧିକ ଜାଣନ୍ତୁ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ଆକ୍ସେସରୀ"</string>
@@ -58,7 +59,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> କନେକ୍ଟ ଥିବାବେଳେ <xliff:g id="APPLICATION">%1$s</xliff:g> ସର୍ବଦା ଖୋଲନ୍ତୁ"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> କନେକ୍ଟ ଥିବାବେଳେ <xliff:g id="APPLICATION">%1$s</xliff:g> ସର୍ବଦା ଖୋଲନ୍ତୁ"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB ଡିବଗିଙ୍ଗ କରିବେ?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"କମ୍ପ୍ୟୁଟର୍‌ର RSA କୀ\' ଆଙ୍ଗୁଠି ଚିହ୍ନ ହେଉଛି:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"କମ୍ପ୍ୟୁଟର୍‌ର RSA କୀ ଫିଙ୍ଗରପ୍ରିଣ୍ଟ୍ ହେଉଛି:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"ସବୁବେଳେ ଏହି କମ୍ପ୍ୟୁଟର୍‌ରୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USBରେ ଡିବଗ୍‍ କରାଯାଇପାରିବ ନାହିଁ"</string>
@@ -110,8 +111,8 @@
     <string name="accessibility_phone_button" msgid="6738112589538563574">"ଫୋନ୍‍"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"ଭଏସ୍‌ ସହାୟକ"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"ଅନଲକ୍‌ କରନ୍ତୁ"</string>
-    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପାଇଁ ଅପେକ୍ଷା କରିଛି"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ଆଙ୍ଗୁଠିଚିହ୍ନ ବ୍ୟବହାର ନକରି ଅନଲକ୍‍ କରନ୍ତୁ"</string>
+    <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ଟିପଚିହ୍ନ ପାଇଁ ଅପେକ୍ଷା କରୁଛି"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ଆପଣଙ୍କ ଟିପଚିହ୍ନ ବ୍ୟବହାର ନକରି ଅନଲକ୍‍ କରନ୍ତୁ"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"ଫେସ୍ ସ୍କାନିଙ୍ଗ କରାଯାଉଛି"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"ପଠାନ୍ତୁ"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିଚାଳନା କରନ୍ତୁ"</string>
@@ -128,22 +129,15 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ସୁନିଶ୍ଚିତ କରାଯାଇଛି"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ସୁନିଶ୍ଚିତ କରନ୍ତୁରେ ଟାପ୍ କରନ୍ତୁ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ପ୍ରାମାଣିକତା ହୋଇଛି"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ପାଟର୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ପାସ୍‌ୱାର୍ଡ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ଭୁଲ PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ଭୁଲ ପାଟର୍ନ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ଭୁଲ ପାସ୍‌ୱାର୍ଡ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ଅନେକ ଥର ଭୁଲ ଚେଷ୍ଟା। \n <xliff:g id="NUMBER">%d</xliff:g>ସେକେଣ୍ଡରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ଟିପଚିହ୍ନ ସେନସର୍‌କୁ ଛୁଅଁନ୍ତୁ"</string>
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଇକନ୍"</string>
+    <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ଆପଣଙ୍କୁ ଚିହ୍ନଟ କରୁଛି…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"ମୁହଁ ଆଇକନ୍"</string>
     <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"କମ୍ପାଟିବିଲିଟୀ ଜୁମ୍ ବଟନ୍।"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ବିଜ୍ଞପ୍ତି"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ଫ୍ଲାସ୍‍ଲାଇଟ୍"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"କ୍ୟାମେରା ବ୍ୟବହାରରେ ଅଛି"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ମୋବାଇଲ୍‌ ଡାଟା"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ଡାଟାର ବ୍ୟବହାର"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ଅବଶିଷ୍ଟ ଡାଟା"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 805a580..18ddddf 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ਇਨਪੁਟ ਵਿਧੀਆਂ ਸੈਟ ਅਪ ਕਰੋ"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ਫਿਜੀਕਲ ਕੀ-ਬੋਰਡ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"ਕੀ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?\nਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"ਕੀ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ਤੱਕ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਨੂੰ ਵਰਤਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹਣੀ ਹੈ?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"ਕੀ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ਨੂੰ ਵਰਤਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹਣੀ ਹੈ?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ਕੋਈ ਇੰਸਟੌਲ ਕੀਤੇ ਐਪਸ ਇਸ USB ਐਕਸੈਸਰੀ ਨਾਲ ਕੰਮ ਨਹੀਂ ਕਰਦੇ। <xliff:g id="URL">%1$s</xliff:g> ਤੇ ਇਸ ਐਕਸੈਸਰੀ ਬਾਰੇ ਹੋਰ ਜਾਣੋ"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ਐਕਸੈਸਰੀ"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"ਪੂਰਾ ਕਰਨ ਲਈ ਪੁਸ਼ਟੀ ਕਰੋ \'ਤੇ ਟੈਪ ਕਰੋ"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ਪ੍ਰਮਾਣਿਤ ਹੋਇਆ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ਪਿੰਨ ਵਰਤੋ"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ਪੈਟਰਨ ਵਰਤੋ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ਪਾਸਵਰਡ ਵਰਤੋ"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"ਗਲਤ ਪਿੰਨ"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ਗਲਤ ਪੈਟਰਨ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"ਗਲਤ ਪਾਸਵਰਡ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ਬਹੁਤ ਸਾਰੀਆਂ ਗ਼ਲਤ ਕੋਸ਼ਿਸ਼ਾਂ।\n<xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਪ੍ਰਤੀਕ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ਤੁਹਾਡੀ ਪਛਾਣ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ਫਲੈਸ਼ਲਾਈਟ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ਕੈਮਰਾ ਵਰਤੋਂ ਵਿੱਚ ਹੈ"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ਡਾਟਾ ਵਰਤੋਂ"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ਬਾਕੀ  ਡਾਟਾ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 16dfff3..44b4112 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguruj metody wprowadzania"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Klawiatura fizyczna"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otworzyć aplikację <xliff:g id="APPLICATION">%1$s</xliff:g> do obsługi urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na obsługę urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otworzyć aplikację <xliff:g id="APPLICATION">%1$s</xliff:g> do obsługi urządzenia <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Zainstalowane aplikacje nie działają z tym akcesorium USB. Więcej informacji: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Akcesorium USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potwierdzono"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Aby zakończyć, kliknij Potwierdź"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Uwierzytelniono"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Użyj kodu PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Użyj wzoru"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Użyj hasła"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nieprawidłowy kod PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nieprawidłowy wzór"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nieprawidłowe hasło"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Zbyt wiele nieudanych prób.\n Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotknij czytnika linii papilarnych"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona odcisku palca"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Szukam Cię…"</string>
@@ -386,8 +379,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Powiadomienia"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Latarka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Aparat w użyciu"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilna transmisja danych"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Użycie danych"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Pozostały limit"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 25ca226..57d64f5 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para usar o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nenhum apl. instalado funciona com o USB. Saiba mais sobre o acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Acessório USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toque em \"Confirmar\" para concluir"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar padrão"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar senha"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorreto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Padrão incorreto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Senha incorreta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Excesso de tentativas incorretas.\nTente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressão digital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Procurando você…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Câmera em uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de dados"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index fdb98fa..6c80211 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos introdução"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Pretende permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao dispositivo <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Pretende permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> aceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicação não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Pretende permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao acessório <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Pretende abrir a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Pretende abrir a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicação não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Pretende abrir a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nenhuma das aplicações instaladas funciona com o acessório USB. Saiba mais acerca do acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Acessório USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmado"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toque em Confirmar para concluir."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Utilizar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Utilizar padrão"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Utilizar palavra-passe"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorreto."</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Padrão incorreto."</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Palavra-passe incorreta."</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Demasiadas tentativas incorretas.\nTente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressões digitais."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"À sua procura…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Câmara em utilização"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilização de dados"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 25ca226..57d64f5 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Teclado físico"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para usar o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Nenhum apl. instalado funciona com o USB. Saiba mais sobre o acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Acessório USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmada"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Toque em \"Confirmar\" para concluir"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autenticado"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Usar PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Usar padrão"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Usar senha"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN incorreto"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Padrão incorreto"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Senha incorreta"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Excesso de tentativas incorretas.\nTente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Toque no sensor de impressão digital"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ícone de impressão digital"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Procurando você…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Câmera em uso"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dados móveis"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de dados"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 171ca9a..a6bd29b 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Setați metode introducere text"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastatură fizică"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Permiteți <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Permiteți accesul aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> la <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nPermisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Permiteți <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> ca să gestioneze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> pentru a gestiona <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nPermisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> ca să gestioneze <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aplic. instal. nu funcț. cu acest acces. USB. Aflați despre acest accesoriu la <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesoriu USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Confirmat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Atingeți Confirmați pentru a finaliza"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentificat"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Folosiți PIN-ul"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Folosiți modelul"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Folosiți parola"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN greșit"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Model greșit"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Parolă greșită"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Prea multe încercări incorecte.\nÎncercați din nou peste <xliff:g id="NUMBER">%d</xliff:g> secunde."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Atingeți senzorul de amprente"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Pictograma amprentă"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Vă căutăm…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificări"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanternă"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Se folosește camera foto"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Date mobile"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilizarea datelor"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Date rămase"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1d7f6c8..3459440 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Настройка способов ввода"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физическая клавиатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nПриложению не разрешено вести запись, однако с помощью этого USB-устройства оно может записывать звук."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>\"?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для управления устройством \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для использования устройства \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nПриложению не разрешено вести запись, однако с помощью этого USB-устройства оно может записывать звук."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для управления устройством \"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>\"?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Приложения не поддерживают это USB-устройство. Подробнее о нем читайте здесь: <xliff:g id="URL">%1$s</xliff:g>."</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-устройство"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Подтверждено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Нажмите \"Подтвердить\""</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Аутентификация выполнена"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Использовать PIN-код"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Использовать графический ключ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Использовать пароль"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Неверный PIN-код."</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Неверный графический ключ."</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Неверный пароль."</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Слишком много неудачных попыток.\nПовторите через <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Прикоснитесь к сканеру отпечатков пальцев."</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок отпечатка пальца"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Поиск лица…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Уведомления"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фонарик"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Используется камера"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобильный Интернет"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Передача данных"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Остается данных"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index fa1c109..ab3dc222 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ආදාන ක්‍රම සකසන්න"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"භෞතික යතුරු පුවරුව"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_DEVICE">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> වෙත ප්‍රවේශ වීමට <xliff:g id="USB_DEVICE">%2$s</xliff:g> හට ඉඩ දෙන්නද?\n මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්‍රව්‍ය ග්‍රහණය කර ගත හැකිය."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> හැසිරවීමට <xliff:g id="APPLICATION">%1$s</xliff:g> විවෘත කරන්නද?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g> හැසිරවීමට විවෘත කරන්නද?\n මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්‍රව්‍ය ග්‍රහණය කර ගත හැකිය."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> හැසිරවීමට <xliff:g id="APPLICATION">%1$s</xliff:g> විවෘත කරන්නද?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"මෙම USB මෙවලම සමග ක්‍රියා කරන ස්ථාපිත යෙදුම් නොමැත. <xliff:g id="URL">%1$s</xliff:g> වලින් මෙම මෙවලම ගැන තව දැනගන්න"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB මෙවලම"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> සම්බන්ධ විට <xliff:g id="APPLICATION">%1$s</xliff:g> සැම විටම විවෘත කරන්න"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> සම්බන්ධ විට <xliff:g id="APPLICATION">%1$s</xliff:g> සැම විටම විවෘත කරන්න"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB නිදොස්කරණයට අවසර දෙනවද?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"මෙම පරිගණකයේ RSA යතුරු ඇඟිලි සටහන වන්නේ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"මෙම පරිගණකයේ RSA යතුරු ඇඟිලි සලකුණ සටහන වන්නේ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"සැම විටම මෙම පරිගණකයෙන් ඉඩ ලබා දෙන්න"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"ඉඩ දෙන්න"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB නිදොස්කරණය වෙත අවසර නැහැ"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"තහවුරු කළා"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"සම්පූර්ණ කිරීමට තහවුරු කරන්න තට්ටු කර."</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"සත්‍යාපනය විය"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN භාවිත කරන්න"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"රටාව භාවිත කරන්න"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"මුරපදය භාවිත කරන්න"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN එක වැරදියි"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"වැරදි රටාවකි"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"වැරදි මුරපදයකි"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"වැරදි උත්සාහයන් ගණන වැඩියි. තත්පර \n තත්පර <xliff:g id="NUMBER">%d</xliff:g>කින් නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ඇඟිලි සලකුණු නිරූපකය"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"ඔබව සොයමින්…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"දැනුම්දීම්"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"සැණෙළි ආලෝකය"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"කැමරාව භාවිතයේ ඇත"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ජංගම දත්ත"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"දත්ත භාවිතය"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ඉතිරි ඇති දත්ත"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ddb0ed4..aa004b4 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavenie metód vstupu"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fyzická klávesnica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> pristupovať k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTejto aplikácii nebolo udelené povolenie na nahrávanie, môže však snímať zvuk cez toto zariadenie USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Otvoriť aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g> na použitie zariadenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Chcete spracovávať zariadenie <xliff:g id="USB_DEVICE">%2$s</xliff:g> pomocou aplikácie <xliff:g id="APPLICATION">%1$s</xliff:g>?\nTejto aplikácii nebolo udelené povolenie na nahrávanie, ale môže nasnímať zvuk cez toto zariadenie USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Otvoriť aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g> na použitie zariadenia <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"S týmto zariad. USB nefunguje žiadna nainštal. aplikácia. Ďalšie informácie na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Periférne zariadenie USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Hlasový asistent"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Odomknúť"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Čaká sa na odtlačok prsta"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Odomknúť bez použitia odtlačku"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Odomknúť bez použitia odtlačku prsta"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Skenovanie tváre"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Odoslať"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Spravovať upozornenia"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potvrdené"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Overenie dokončíte klepnutím na Potvrdiť"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Overené"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Použiť PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Použiť vzor"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Použiť heslo"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nesprávny PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Nesprávny vzor"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nesprávne heslo"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Príliš veľa nesprávnych pokusov. \nSkúste to znova o <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotknite sa senzora odtlačkov prstov"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona odtlačku prsta"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hľadáme vás…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Upozornenia"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Baterka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparát sa používa"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobilné dáta"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Spotreba dát"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Zostávajúce údaje"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1af84fe..03fa751 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavi načine vnosa"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fizična tipkovnica"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do dodatka USB <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do dodatka USB <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Želite odpreti aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje dodatka USB <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Želite odpreti aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Želite odpreti aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje dodatka USB <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Namešč. prog. ne delujejo s tem dodatkom USB. Več o tem dodatku preberite na <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Dodatek USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Potrjeno"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Za dokončanje se dotaknite »Potrdite«"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Preverjena pristnost"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Uporabi kodo PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Uporabi vzorec"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Uporabi geslo"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Napačna koda PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Napačen vzorec"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Napačno geslo"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Preveč napačnih poskusov.\nPoskusite znova čez <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Dotaknite se tipala prstnih odtisov"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona prstnih odtisov"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Preverjanje vašega obraza …"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obvestila"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svetilka"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Fotoaparat je v uporabi"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Prenos podatkov v mobilnem omrežju"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Poraba podatkov"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podatkov"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 344aae3..21915c9 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguro metodat e hyrjes"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tastierë fizike"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Të lejohet <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Dëshiron të lejosh që <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nKëtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Të lejohet <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Të hapet <xliff:g id="APPLICATION">%1$s</xliff:g> për të përdorur <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Dëshiron të hapësh <xliff:g id="APPLICATION">%1$s</xliff:g> që të përpunojë <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nKëtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Të hapet <xliff:g id="APPLICATION">%1$s</xliff:g> për të përdorur <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Asnjë aplikacion i instaluar nuk punon me këtë ndihmës USB-je. Mëso më shumë rreth këtij ndihmësi në <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Qasja në USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Konfirmuar"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Trokit \"Konfirmo\" për ta përfunduar"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"U vërtetua"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Përdor kodin PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Përdor motivin"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Përdor fjalëkalimin"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Kod PIN i gabuar"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Motiv i gabuar"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Fjalëkalim i gabuar"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Shumë tentativa të pasakta.\nProvo përsëri brenda <xliff:g id="NUMBER">%d</xliff:g> sekondash."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Prek sensorin e gjurmës së gishtit"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikona e gjurmës së gishtit"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Po të kërkojmë…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Njoftimet"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Elektriku"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera në përdorim"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Të dhënat celulare"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Përdorimi i të dhënave"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Të dhënat e mbetura"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index b36b9dc..64ab59b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Подеси методе уноса"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Физичка тастатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nОва апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> да бисте користили уређај <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> ради руковања уређајем <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nОва апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> да бисте користили уређај <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Инсталиране апликације не функционишу са овим USB помоћним уређајем. Сазнајте више о њему на адреси <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB помоћни уређај"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Потврђено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Додирните Потврди да бисте завршили"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Идентитет је потврђен"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Користите PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Користите шаблон"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Користите лозинку"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Погрешан PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Погрешан шаблон"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Погрешна лозинка"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Превише нетачних покушаја.\n Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Додирните сензор за отисак прста"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Икона отиска прста"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Тражимо вас…"</string>
@@ -382,8 +375,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Обавештења"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Лампа"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Користи се камера"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобилни подаци"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Потрошња података"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Преостала количина података"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 24e0b1e..0a65cc7 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurera inmatningsmetoder"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysiskt tangentbord"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAppen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> och hantera <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> för att hantera <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAppen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> och hantera <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Inga appar fungerar med det här USB-tillbehöret. Läs mer om det på <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB-tillbehör"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Bekräftat"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Slutför genom att trycka på Bekräfta"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Autentiserad"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Använd pinkod"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Använd grafiskt lösenord"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Använd lösenord"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Fel pinkod"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Fel grafiskt lösenord"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Fel lösenord"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"För många felaktiga försök.\nFörsök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Tryck på fingeravtryckssensorn"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Ikon för fingeravtryck"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Håller utkik efter dig …"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Aviseringar"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ficklampa"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kameran används"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Dataanvändning"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Återstående data"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 93f5b7d..48c1fab 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Weka mbinu za ingizo"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Kibodi halisi"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nProgramu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ili itumie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ishughulikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nProgramu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ili itumie <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Hakuna programu zilizosakinishwa zinazofanya kazi na kifaa hiki cha USB. Pata maelezo zaidi kuhusu kifaa hiki kwenye <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Kifaa cha Usb"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"Fungua <xliff:g id="APPLICATION">%1$s</xliff:g> kila wakati <xliff:g id="USB_DEVICE">%2$s</xliff:g> inaunganishwa"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Fungua <xliff:g id="APPLICATION">%1$s</xliff:g> kila wakati <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> inaunganishwa"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Ruhusu utatuaji wa USB?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"Alama ya kidole ya kitufe cha RSA ya kompyuta ni:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"Kitambulisho dijitali cha kifunguo cha RSA cha kompyuta ni:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Ruhusu kutoka kwenye kompyuta hii kila wakati"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Ruhusu"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Utatuzi wa USB hauruhusiwi"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Mapendekezo ya Sauti"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Fungua"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Inasubiri alama ya kidole"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Fungua bila kutumia kitambulisho chako"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Fungua bila kutumia alama ya kidole chako"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Inachanganua uso"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Tuma"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Dhibiti arifa"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Imethibitishwa"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Gusa Thibitisha ili ukamilishe"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Umethibitishwa"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Tumia PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Tumia mchoro"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Tumia nenosiri"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Nambari ya PIN si sahihi"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Mchoro si sahihi"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Nenosiri si sahihi"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Majaribio mengi mno yasiyo sahihi.\nJaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Gusa kitambua alama ya kidole"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Aikoni ya alama ya kidole"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Inakutafuta…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Arifa"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Tochi"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera inatumika"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Data ya simu"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Matumizi ya data"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Data iliyosalia"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a5aa91d..7263bf6 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"உள்ளீட்டு முறைகளை அமை"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"கைமுறை விசைப்பலகை"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐப் பயன்படுத்த <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ அனுமதிக்கவா?\nஇந்த ஆப்ஸிற்கு ரெக்கார்டு செய்வதற்கான அனுமதி வழங்கப்படவில்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்யும்."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐக் கையாள <xliff:g id="APPLICATION">%1$s</xliff:g>ஐத் திறக்கவா?\nஇந்த ஆப்ஸிற்கு ரெக்கார்டு செய்வதற்கான அனுமதி வழங்கப்படவில்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்ய முடியும்."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"நிறுவிய ஆப்ஸ் எதுவும், USB துணைக்கருவியுடன் இயங்காது. <xliff:g id="URL">%1$s</xliff:g> இல் துணைக்கருவி குறித்து மேலும் அறிக"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB துணைக்கருவி"</string>
@@ -58,7 +58,7 @@
     <string name="always_use_device" msgid="4015357883336738417">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> இணைக்கப்பட்டிருக்கையில், <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ எப்போதும் திற"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> இணைக்கப்பட்டிருக்கையில், <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ எப்போதும் திற"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"USB பிழைதிருத்தத்தை அனுமதிக்கவா?"</string>
-    <string name="usb_debugging_message" msgid="2220143855912376496">"பின்வருவது கணினியின் RSA விசை கைரேகையாகும்:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+    <string name="usb_debugging_message" msgid="2220143855912376496">"கணினியின் RSA விசை ஃபிங்கர்பிரிண்ட்:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"இந்தக் கணினியிலிருந்து எப்போதும் அனுமதி"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"அனுமதி"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB பிழைதிருத்தம் அனுமதிக்கப்படவில்லை"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"உறுதிப்படுத்தப்பட்டது"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"முடிக்க \'உறுதிப்படுத்து\' என்பதை தட்டவும்"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"அங்கீகரிக்கப்பட்டது"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"பின்னைப் பயன்படுத்து"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"பேட்டர்னைப் பயன்படுத்து"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"கடவுச்சொல்லைப் பயன்படுத்து"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"தவறான பின்"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"தவறான பேட்டர்ன்"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"தவறான கடவுச்சொல்"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"பல தவறான முயற்சிகள்.\n<xliff:g id="NUMBER">%d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"கைரேகை சென்சாரைத் தொடவும்"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"கைரேகை ஐகான்"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"உங்கள் முகத்தைத் தேடுகிறது…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"அறிவிப்புகள்"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"டார்ச் லைட்"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"கேமரா உபயோகத்திலுள்ளது"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"மொபைல் டேட்டா"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"டேட்டா உபயோகம்"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"மீதமுள்ள தரவு"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index c6b2bb7..af330f18f 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ఇన్‌పుట్ పద్ధతులను సెటప్ చేయండి"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"భౌతిక కీబోర్డ్"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని అనుమతించాలా?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ను అనుమతించాలా?\nఈ యాప్‌నకు రికార్డ్ చేసే అనుమతి మంజూరు చేయబడలేదు, కానీ ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ని యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని అనుమతించాలా?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని నిర్వహించడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని తెరవాలా?"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ని నిర్వహించడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని తెరవాలా?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ఈ USB ఉపకరణంతో ఇన్‌స్టాల్ చేయబడిన అనువర్తనాలు ఏవీ పని చేయవు. ఈ ఉపకరణం గురించి <xliff:g id="URL">%1$s</xliff:g>లో మరింత తెలుసుకోండి"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB ఉపకరణం"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"నిర్ధారించబడింది"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"పూర్తి చేయడానికి \"నిర్ధారించు\" నొక్కండి"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ప్రామాణీకరించబడింది"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"పిన్‌ను ఉపయోగించు"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ఆకృతిని ఉపయోగించు"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"పాస్‌వర్డ్‌ను ఉపయోగించు"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"పిన్ తప్పు"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"ఆకృతి తప్పు"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"పాస్‌వర్డ్ తప్పు"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"చాలా ఎక్కువ తప్పు ప్రయత్నాలు చేశారు.\n<xliff:g id="NUMBER">%d</xliff:g> సెకన్ల తర్వాత మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"వేలిముద్ర సెన్సార్‌ను తాకండి"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"వేలిముద్ర చిహ్నం"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"మీ కోసం చూస్తోంది…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"నోటిఫికేషన్‌లు"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ఫ్లాష్‌లైట్"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"కెమెరా ఉపయోగంలో ఉంది"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"మొబైల్ డేటా"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"డేటా వినియోగం"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"మిగిలిన డేటా"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2907524..fc062b4 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ตั้งค่าวิธีการป้อนข้อมูล"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"แป้นพิมพ์บนเครื่อง"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม\nแอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่จะอัดเสียงผ่านอุปกรณ์ USB นี้ได้"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ใช่ไหม\nแอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่จะอัดเสียงผ่านอุปกรณ์ USB นี้ได้"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"แอปพลิเคชันที่ติดตั้งใช้กับอุปกรณ์ USB นี้ไม่ได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับอุปกรณ์เสริมนี้ที่ <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"อุปกรณ์เสริม USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"ยืนยันแล้ว"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"แตะยืนยันเพื่อดำเนินการให้เสร็จสมบูรณ์"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"ตรวจสอบสิทธิ์แล้ว"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"ใช้ PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"ใช้รูปแบบ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"ใช้รหัสผ่าน"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN ไม่ถูกต้อง"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"รูปแบบไม่ถูกต้อง"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"รหัสผ่านไม่ถูกต้อง"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"ดำเนินการไม่ถูกต้องหลายครั้งเกินไป\nลองอีกครั้งใน <xliff:g id="NUMBER">%d</xliff:g> วินาที"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"แตะเซ็นเซอร์ลายนิ้วมือ"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"ไอคอนลายนิ้วมือ"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"กำลังหาใบหน้าคุณ…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"การแจ้งเตือน"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ไฟฉาย"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"ใช้กล้องอยู่"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"เน็ตมือถือ"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"การใช้อินเทอร์เน็ต"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ข้อมูลที่เหลืออยู่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ce8c88b..37dd49f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"I-set up paraan ng pag-input"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Aktwal na keyboard"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na ma-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nHindi nabigyan ng pahintulot ang app na ito para mag-record pero nakakapag-capture ito ng audio sa pamamagitan ng USB device na ito."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na ma-access ang <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> upang pamahalaan ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> para pangasiwaan ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nHindi nabigyan ng pahintulot ang app na ito para mag-record pero nakakapag-capture ito ng audio sa pamamagitan ng USB device na ito."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> upang pamahalaan ang <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Wala sa mga na-install na app ang gumagana sa USB accessory na ito. Matuto pa tungkol sa accessory na ito sa <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Nakumpirma"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"I-tap ang Kumpirmahin para kumpletuhin"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Na-authenticate"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Gumamit ng PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Gumamit ng pattern"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Gumamit ng password"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Maling PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Maling pattern"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Maling password"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Masyadong maraming maling pagsubok.\nSubukan ulit sa loob ng <xliff:g id="NUMBER">%d</xliff:g> (na) segundo."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Pindutin ang fingerprint sensor"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Icon ng fingerprint"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Hinahanap ka…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Mga Notification"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Ginagamit na camera"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobile data"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Paggamit ng data"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Natitirang data"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 7976014..c052f4a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Giriş yöntemlerini ayarla"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziksel klavye"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?\nBu uygulamaya kayıt izni verilmemiş ancak bu USB cihazı aracılığıyla sesleri yakalayabilir."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> aksesuarına erişmesine izin verilsin mi?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını işlemek için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?\n Bu uygulamaya kayıt izni verilmemiş, ancak bu USB cihazı aracılığıyla sesleri yakalabilir."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> aksesuarını işlemek için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Bu USB aksesuarıyla çalışan yüklü uygulama yok. Bu aksesuar hakkında bilgi için: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB aksesuarı"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Onaylandı"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tamamlamak için Onayla\'ya dokunun"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Kimliği Doğrulandı"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN kullan"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Deseni kullan"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Şifre kullan"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Yanlış PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Yanlış desen"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Yanlış şifre"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Çok fazla yanlış giriş yapıldı.\n<xliff:g id="NUMBER">%d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Parmak izi sensörüne dokunun"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Parmak izi simgesi"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Yüzünüz tanınmaya çalışılıyor…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirimler"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Fener"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera kullanımda"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil veri"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Veri kullanımı"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Kalan veri"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index ea2f376..de6b6f2 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Налаштувати методи введення"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Фізична клавіатура"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до такого аксесуара: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nЦей додаток не має дозволу на записування звуку, але може фіксувати його через цей USB-пристрій."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до такого аксесуара: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Відкрити додаток <xliff:g id="APPLICATION">%1$s</xliff:g>, щоб використовувати такий аксесуар: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Працювати з пристроєм \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\" у додатку <xliff:g id="APPLICATION">%1$s</xliff:g>?\nУ цього додатка немає дозволів на запис, але він може передавати звук у USB-пристрій."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Відкрити додаток <xliff:g id="APPLICATION">%1$s</xliff:g>, щоб використовувати такий аксесуар: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Установлені прогр. не працюють із цим аксесуаром USB. Більше про цей аксесуар: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Пристрій USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Голосові підказки"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Розблокувати"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Очікується відбиток пальця"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Розблокувати без цифрового відбитка"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Розблокувати без відбитка пальця"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Сканування обличчя"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Надіслати"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Керувати сповіщеннями"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Підтверджено"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Щоб завершити, натисніть \"Підтвердити\""</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Автентифіковано"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Ввести PIN-код"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Намалювати ключ"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Ввести пароль"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Неправильний PIN-код"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Неправильний ключ"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Неправильний пароль"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Забагато невдалих спроб.\nПовторіть за <xliff:g id="NUMBER">%d</xliff:g> с."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Торкніться сканера відбитків пальців"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Значок відбитка пальця"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Пошук обличчя…"</string>
@@ -384,8 +377,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Сповіщення"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ліхтарик"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Використовується камера"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Мобільне передавання даних"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Використання даних"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Залишилося даних"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 1c28431..b361a4a 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -47,10 +47,11 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ان پٹ کے طریقوں کو ترتیب دیں"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"طبعی کی بورڈ"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"‏<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی دیں؟\nاس ایپ کو ریکارڈ کی اجازت عطا نہیں کی گئی ہے مگر اس USB آلہ سے کیپچر کر سکتے ہیں۔"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ہینڈل کرنے کیلئے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟"</string>
+    <!-- no translation found for usb_device_confirm_prompt_warn (210658281376801521) -->
+    <skip />
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ہینڈل کرنے کیلئے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"‏اس USB لوازم کے ساتھ کوئی انسٹال کردہ ایپس کام نہیں کرتی ہیں۔ <xliff:g id="URL">%1$s</xliff:g> پر مزید جانیں"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"‏USB لوازم"</string>
@@ -128,20 +129,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"تصدیق شدہ"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"مکمل کرنے کیلئے \'تصدیق کریں\' تھپتھپائیں"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"تصدیق کردہ"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"‏PIN استعمال کریں"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"پیٹرن کا استعمال کریں"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"پاس ورڈ استعمال کریں"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"‏غلط PIN"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"غلط پیٹرن"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"غلط پاس ورڈ"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"کافی زیادہ غلط کوششیں کی گئیں۔\n <xliff:g id="NUMBER">%d</xliff:g> سیکنڈ بعد دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"فنگر پرنٹ سینسر پر ٹچ کریں"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"فنگر پرنٹ آئیکن"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"آپ کے لیے تلاش کیا جا رہا ہے…"</string>
@@ -380,8 +374,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"اطلاعات"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"فلیش لائٹ"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"کیمرا زیر استعمال ہے"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"موبائل ڈیٹا"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ڈیٹا کا استعمال"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"باقی ڈیٹا"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index c3e39e5..5c077d8 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Kiritish usullarini moslash"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Tashqi tugmatag"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanishga ruxsat berilsinmi?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanish uchun ruxsat berilsinmi?\nBu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> qurilmasidan foydalanishga ruxsat berilsinmi?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> bilan ishlash uchun <xliff:g id="APPLICATION">%1$s</xliff:g> ochilsinmi?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanish uchun ruxsat berilsinmi?\nBu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> bilan ishlash uchun <xliff:g id="APPLICATION">%1$s</xliff:g> ochilsinmi?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Bu USB jihoz bilan ishlash uchun dastur o‘rnatilmagan.Ushbu jihoz haqida: <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB jihoz"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Tasdiqlangan"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Tasdiqlash uchun tegining"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Tasdiqlandi"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"PIN kod kiritish"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Grafik kalitdan foydalanish"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Paroldan foydalanish"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN kod xato"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Grafik kalit xato"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Parol xato"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Xato urinishlar soni oshib ketdi! \n <xliff:g id="NUMBER">%d</xliff:g> soniyadan keyin qayta urining."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Barmoq izi skaneriga tegining"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Barmoq izi belgisi"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Yuzingiz tekshirilmoqda…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirishnomalar"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Fonar"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Kamera ishlatilmoqda"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobil internet"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Trafik sarfi"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Qolgan trafik"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d2da39b..88849c8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Thiết lập phương thức nhập"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Bàn phím vật lý"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập vào <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nỨng dụng này chưa được cấp quyền ghi âm nhưng vẫn có thể ghi âm thông qua thiết bị USB này."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDù chưa được cấp quyền ghi âm, nhưng ứng dụng có thể ghi âm thông qua thiết bị USB này."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Không có ứng dụng được cài đặt nào hoạt động với phụ kiện USB này. Tìm hiểu thêm về phụ kiện này tại <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Phụ kiện USB"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Ðã xác nhận"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Nhấn vào Xác nhận để hoàn tất"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Đã xác thực"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Dùng mã PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Dùng hình mở khóa"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Dùng mật khẩu"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Mã PIN sai"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Hình mở khóa sai"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Mật khẩu sai"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Bạn đã nhập sai quá nhiều lần.\nHãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây."</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Chạm vào cảm biến vân tay"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Biểu tượng vân tay"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Đang tìm kiếm bạn…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn pin"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Máy ảnh đang được sử dụng"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Dữ liệu di động"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Sử dụng dữ liệu"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dữ liệu còn lại"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 551e54e..cdc2070 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"设置输入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"物理键盘"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"要允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"是否允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\n此应用未获得录音权限,但能通过此 USB 设备录制音频。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"要允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>吗?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来处理<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来使用<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?\n此应用未获得录音权限,但能通过此 USB 设备录制音频。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来处理<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>吗?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"未安装此USB配件适用的应用。要了解此配件的详情,请访问:<xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB配件"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"已确认"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"点按“确认”即可完成"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"已经过身份验证"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"使用 PIN 码"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"使用图案"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"使用密码"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN 码错误"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"图案错误"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"密码错误"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"输错次数过多。\n请在 <xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"请触摸指纹传感器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指纹图标"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在查找您的面孔…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手电筒"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"相机正在使用中"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"移动数据"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"流量使用情况"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩余流量"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 206fcfc..a69bb7b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"實體鍵盤"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式來控制「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"已安裝的應用程式均無法存取這個 USB 配件,如要進一步瞭解這個配件,請瀏覽 <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB 配件"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"已確認"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"輕按 [確定] 以完成"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"驗證咗"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"使用 PIN"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"使用圖案"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"使用密碼"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN 錯誤"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"圖案錯誤"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"密碼錯誤"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"輸入錯誤的次數太多,\n請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"請輕觸指紋感應器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋圖示"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在搜尋您的臉孔…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"電筒"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"相機使用中"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"流動數據"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"數據用量"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩餘資料"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index c1f299d..dedaebf 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入法"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"實體鍵盤"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n這個應用程式未取得錄製權限,但可以透過這部 USB 裝置錄製音訊。"</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」來使用「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n這個應用程式未取得錄製內容的權限,但可以透過這部 USB 裝置錄製音訊。"</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"已安裝的應用程式均無法存取這個 USB 配件,如要進一步瞭解這個配件,請造訪 <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB 配件"</string>
@@ -128,20 +128,13 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"確認完畢"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"輕觸 [確認] 完成驗證設定"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"已通過驗證"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"使用 PIN 碼"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"使用解鎖圖案"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"使用密碼"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"PIN 碼錯誤"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"圖案錯誤"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"密碼錯誤"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"錯誤次數過多,\n請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試。"</string>
     <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"請輕觸指紋感應器"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"指紋圖示"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"正在尋找你的臉孔…"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手電筒"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"正在使用相機"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"行動數據"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"數據用量"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩餘資料"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 37eca51..192bfb4 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -47,10 +47,10 @@
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Izilungiselelo zezindlela zokufakwayo"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Ukwakheka kwekhibhodi"</string>
     <string name="usb_device_permission_prompt" msgid="1825685909587559679">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukufinyelela i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
-    <!-- no translation found for usb_device_permission_prompt_warn (1842558472039505091) -->
-    <skip />
+    <string name="usb_device_permission_prompt_warn" msgid="1842558472039505091">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ifinyelele ku-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLolu hlelo lokusebenza alunikeziwe imvume yokurekhoda kodwa lingathatha umsindo ngale divayisi ye-USB."</string>
     <string name="usb_accessory_permission_prompt" msgid="2465531696941369047">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukufinyelela i-<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_device_confirm_prompt" msgid="7440562274256843905">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphath i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string>
+    <string name="usb_device_confirm_prompt_warn" msgid="210658281376801521">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphathe i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLolu hlelo lokusebenza alinikeziwe imvume yokurekhoda kodwa lingathatha umsindo ngale divayisi ye-USB."</string>
     <string name="usb_accessory_confirm_prompt" msgid="4333670517539993561">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphath i-<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Azikho izinhlelo zokusebenza ezisebenze ngezinto ze-USB. Funda okwengeziwe ngale into kwi <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"ama-accessory e-USB"</string>
@@ -111,7 +111,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"Isisekeli sezwi"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"Vula"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Ilindele izigxivizo zeminwe"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Vula ngaphandle kokusebenzisa izigxivizo zakho zeminwe"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Vula ngaphandle kokusebenzisa izigxivizo zeminwe zakho"</string>
     <string name="accessibility_scanning_face" msgid="769545173211758586">"Ukuskena ubuso"</string>
     <string name="accessibility_send_smart_reply" msgid="7766727839703044493">"Thumela"</string>
     <string name="accessibility_manage_notification" msgid="2026361503393549753">"Phatha izaziso"</string>
@@ -128,21 +128,14 @@
     <string name="biometric_dialog_face_icon_description_confirmed" msgid="2003141400387093967">"Kuqinisekisiwe"</string>
     <string name="biometric_dialog_tap_confirm" msgid="4540715260292022404">"Thepha okuthi Qinisekisa ukuze uqedele"</string>
     <string name="biometric_dialog_authenticated" msgid="5918352844999713693">"Kugunyaziwe"</string>
-    <!-- no translation found for biometric_dialog_use_pin (2506187927478996039) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_pattern (4721877831431699442) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_use_password (3426428493718969343) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pin (4600590473629948574) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_pattern (4808369401645512099) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_wrong_password (2343518162282889518) -->
-    <skip />
-    <!-- no translation found for biometric_dialog_credential_too_many_attempts (1556206869468265728) -->
-    <skip />
-    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Thinta inzwa yesigxivizo somunwe"</string>
+    <string name="biometric_dialog_use_pin" msgid="2506187927478996039">"Sebenzisa iphinikhodi"</string>
+    <string name="biometric_dialog_use_pattern" msgid="4721877831431699442">"Sebenzisa iphethini"</string>
+    <string name="biometric_dialog_use_password" msgid="3426428493718969343">"Sebenzisa iphasiwedi"</string>
+    <string name="biometric_dialog_wrong_pin" msgid="4600590473629948574">"Iphinikhodi engalungile"</string>
+    <string name="biometric_dialog_wrong_pattern" msgid="4808369401645512099">"Iphethini engalungile"</string>
+    <string name="biometric_dialog_wrong_password" msgid="2343518162282889518">"Iphasiwedi engalungile"</string>
+    <string name="biometric_dialog_credential_too_many_attempts" msgid="1556206869468265728">"Imizamo eminingi kakhulu engalungile.\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER">%d</xliff:g>."</string>
+    <string name="fingerprint_dialog_touch_sensor" msgid="8511557690663181761">"Thinta inzwa yesigxivizo zeminwe"</string>
     <string name="accessibility_fingerprint_dialog_fingerprint_icon" msgid="3125122495414253226">"Isithonjana sezigxivizo zeminwe"</string>
     <string name="face_dialog_looking_for_face" msgid="7049276266074494689">"Kufunwa wena…"</string>
     <string name="accessibility_face_dialog_face_icon" msgid="2658119009870383490">"Isithonjana sobuso"</string>
@@ -380,8 +373,7 @@
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Izaziso"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"I-Flashlight"</string>
-    <!-- no translation found for quick_settings_flashlight_camera_in_use (6120370795890963385) -->
-    <skip />
+    <string name="quick_settings_flashlight_camera_in_use" msgid="6120370795890963385">"Ikhamera esetshenziswayo"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Idatha yeselula"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Ukusetshenziswa kwedatha"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Idatha esele"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d722d61..14371fe 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1164,4 +1164,11 @@
 
     <!-- Size of the RAT type for CellularTile -->
     <dimen name="celltile_rat_type_size">10sp</dimen>
+
+    <dimen name="new_qs_vertical_margin">8dp</dimen>
+
+    <!-- Size of media cards in the QSPanel carousel -->
+    <dimen name="qs_media_height">150dp</dimen>
+    <dimen name="qs_media_width">350dp</dimen>
+    <dimen name="qs_media_padding">8dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3cc683a..0082949 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -461,13 +461,13 @@
     <string name="data_connection_lte_plus">LTE+</string>
 
     <!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5ge" translate="false">5Ge</string>
+    <string name="data_connection_5ge" translatable="false">5Ge</string>
 
     <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g" translate="false">5G</string>
+    <string name="data_connection_5g" translatable="false">5G</string>
 
     <!-- Content description of the data connection type 5G+. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translate="false">5G+</string>
+    <string name="data_connection_5g_plus" translatable="false">5G+</string>
 
     <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] -->
     <string name="data_connection_cdma">1X</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 00e8b53..70f8e15 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -78,6 +78,7 @@
 
     // Should match the values in PhoneWindowManager
     public static final String CLOSE_SYSTEM_WINDOWS_REASON_RECENTS = "recentapps";
+    public static final String CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY = "homekey";
 
     private final PackageManager mPackageManager;
     private final BackgroundExecutor mBackgroundExecutor;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index ebac3d9..caee8cc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -131,8 +131,7 @@
     protected void verifyPasswordAndUnlock() {
         if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
 
-        final LockscreenCredential password =
-                LockscreenCredential.createPassword(getPasswordText());
+        final LockscreenCredential password = getEnteredCredential();
         setPasswordEntryInputEnabled(false);
         if (mPendingLockCheck != null) {
             mPendingLockCheck.cancel(false);
@@ -223,7 +222,7 @@
     }
 
     protected abstract void resetPasswordText(boolean animate, boolean announce);
-    protected abstract CharSequence getPasswordText();
+    protected abstract LockscreenCredential getEnteredCredential();
     protected abstract void setPasswordEntryEnabled(boolean enabled);
     protected abstract void setPasswordEntryInputEnabled(boolean enabled);
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 12c9fc9..f8f3dc8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -36,6 +36,7 @@
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
+import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.TextViewInputDisabler;
 import com.android.systemui.R;
 
@@ -243,8 +244,8 @@
     }
 
     @Override
-    protected CharSequence getPasswordText() {
-        return mPasswordEntry.getText();
+    protected LockscreenCredential getEnteredCredential() {
+        return LockscreenCredential.createPasswordOrNone(mPasswordEntry.getText());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 8e9df55..c67decc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -23,6 +23,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
+import com.android.internal.widget.LockscreenCredential;
 import com.android.systemui.R;
 
 /**
@@ -167,8 +168,8 @@
     }
 
     @Override
-    protected CharSequence getPasswordText() {
-        return mPasswordEntry.getText();
+    protected LockscreenCredential getEnteredCredential() {
+        return LockscreenCredential.createPinOrNone(mPasswordEntry.getText());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ac5e255..27410be 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -39,7 +39,6 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
 
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
@@ -101,6 +100,7 @@
 import com.android.settingslib.WirelessUtils;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainLooper;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -118,7 +118,6 @@
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -1500,7 +1499,7 @@
 
     @VisibleForTesting
     @Inject
-    protected KeyguardUpdateMonitor(Context context, @Named(MAIN_LOOPER_NAME) Looper mainLooper) {
+    protected KeyguardUpdateMonitor(Context context, @MainLooper Looper mainLooper) {
         mContext = context;
         mSubscriptionManager = SubscriptionManager.from(context);
         mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index ff8a932..486d02c 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -40,6 +40,10 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.MainLooper;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.ScreenLifecycle;
@@ -148,16 +152,16 @@
     /**
      * Key for getting a the main looper.
      */
-    public static final String MAIN_LOOPER_NAME = "main_looper";
+    private static final String MAIN_LOOPER_NAME = "main_looper";
 
     /**
      * Key for getting a background Looper for background work.
      */
-    public static final String BG_LOOPER_NAME = "background_looper";
+    private static final String BG_LOOPER_NAME = "background_looper";
     /**
      * Key for getting a background Handler for background work.
      */
-    public static final String BG_HANDLER_NAME = "background_handler";
+    private static final String BG_HANDLER_NAME = "background_handler";
     /**
      * Key for getting a Handler for receiving time tick broadcasts on.
      */
@@ -165,7 +169,7 @@
     /**
      * Generic handler on the main thread.
      */
-    public static final String MAIN_HANDLER_NAME = "main_handler";
+    private static final String MAIN_HANDLER_NAME = "main_handler";
 
     /**
      * An email address to send memory leak reports to by default.
@@ -300,10 +304,10 @@
     @Inject Lazy<AutoHideController> mAutoHideController;
     @Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener;
     @Inject Lazy<PrivacyItemController> mPrivacyItemController;
-    @Inject @Named(BG_LOOPER_NAME) Lazy<Looper> mBgLooper;
-    @Inject @Named(BG_HANDLER_NAME) Lazy<Handler> mBgHandler;
-    @Inject @Named(MAIN_LOOPER_NAME) Lazy<Looper> mMainLooper;
-    @Inject @Named(MAIN_HANDLER_NAME) Lazy<Handler> mMainHandler;
+    @Inject @BgLooper Lazy<Looper> mBgLooper;
+    @Inject @BgHandler Lazy<Handler> mBgHandler;
+    @Inject @MainLooper Lazy<Looper> mMainLooper;
+    @Inject @MainHandler Lazy<Handler> mMainHandler;
     @Inject @Named(TIME_TICK_HANDLER_NAME) Lazy<Handler> mTimeTickHandler;
     @Nullable
     @Inject @Named(LEAK_REPORT_EMAIL_NAME) Lazy<String> mLeakReportEmail;
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index df0d787..795a8ce3 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -21,10 +21,13 @@
 import android.util.SparseArray;
 
 import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+
 /**
  * Tracks state of foreground services and notifications related to foreground services per user.
  */
@@ -33,9 +36,11 @@
 
     private final SparseArray<ForegroundServicesUserState> mUserServices = new SparseArray<>();
     private final Object mMutex = new Object();
+    private final NotificationEntryManager mEntryManager;
 
     @Inject
-    public ForegroundServiceController() {
+    public ForegroundServiceController(NotificationEntryManager entryManager) {
+        mEntryManager = entryManager;
     }
 
     /**
@@ -90,11 +95,18 @@
     }
 
     /**
-     * Records active app ops. App Ops are stored in FSC in addition to NotificationData in
-     * case they change before we have a notification to tag.
+     * Records active app ops and updates the app op for the pending or visible notifications
+     * with the given parameters.
+     * App Ops are stored in FSC in addition to NotificationEntry in case they change before we
+     * have a notification to tag.
+     * @param appOpCode code for appOp to add/remove
+     * @param uid of user the notification is sent to
+     * @param packageName package that created the notification
+     * @param active whether the appOpCode is active or not
      */
-    public void onAppOpChanged(int code, int uid, String packageName, boolean active) {
+    public void onAppOpChanged(int appOpCode, int uid, String packageName, boolean active) {
         int userId = UserHandle.getUserId(uid);
+        // Record active app ops
         synchronized (mMutex) {
             ForegroundServicesUserState userServices = mUserServices.get(userId);
             if (userServices == null) {
@@ -102,9 +114,30 @@
                 mUserServices.put(userId, userServices);
             }
             if (active) {
-                userServices.addOp(packageName, code);
+                userServices.addOp(packageName, appOpCode);
             } else {
-                userServices.removeOp(packageName, code);
+                userServices.removeOp(packageName, appOpCode);
+            }
+        }
+
+        // Update appOp if there's an associated pending or visible notification:
+        final String foregroundKey = getStandardLayoutKey(userId, packageName);
+        if (foregroundKey != null) {
+            final NotificationEntry entry = mEntryManager.getPendingOrCurrentNotif(foregroundKey);
+            if (entry != null
+                    && uid == entry.getSbn().getUid()
+                    && packageName.equals(entry.getSbn().getPackageName())) {
+                boolean changed;
+                synchronized (entry.mActiveAppOps) {
+                    if (active) {
+                        changed = entry.mActiveAppOps.add(appOpCode);
+                    } else {
+                        changed = entry.mActiveAppOps.remove(appOpCode);
+                    }
+                }
+                if (changed) {
+                    mEntryManager.updateNotifications("appOpChanged pkg=" + packageName);
+                }
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
index 5c561e5..362014f 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
@@ -50,13 +50,13 @@
 
     @Override
     public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
-        if ((entry.notification.getNotification().flags
+        if ((entry.getSbn().getNotification().flags
                 & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
             return false;
         }
 
         long currentTime = System.currentTimeMillis();
-        return currentTime - entry.notification.getPostTime() < MIN_FGS_TIME_MS;
+        return currentTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
     }
 
     @Override
@@ -79,12 +79,12 @@
             if (mManagedEntries.contains(entry)) {
                 mManagedEntries.remove(entry);
                 if (mNotificationSafeToRemoveCallback != null) {
-                    mNotificationSafeToRemoveCallback.onSafeToRemove(entry.key);
+                    mNotificationSafeToRemoveCallback.onSafeToRemove(entry.getKey());
                 }
             }
         };
         long delayAmt = MIN_FGS_TIME_MS
-                - (System.currentTimeMillis() - entry.notification.getPostTime());
+                - (System.currentTimeMillis() - entry.getSbn().getPostTime());
         mHandler.postDelayed(r, delayAmt);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index f9d8771..b983966 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.statusbar.NotificationVisibility;
@@ -40,6 +41,7 @@
 
     private final Context mContext;
     private final ForegroundServiceController mForegroundServiceController;
+    private final NotificationEntryManager mEntryManager;
 
     @Inject
     public ForegroundServiceNotificationListener(Context context,
@@ -47,15 +49,16 @@
             NotificationEntryManager notificationEntryManager) {
         mContext = context;
         mForegroundServiceController = foregroundServiceController;
-        notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+        mEntryManager = notificationEntryManager;
+        mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
             public void onPendingEntryAdded(NotificationEntry entry) {
-                addNotification(entry.notification, entry.getImportance());
+                addNotification(entry, entry.getImportance());
             }
 
             @Override
-            public void onPostEntryUpdated(NotificationEntry entry) {
-                updateNotification(entry.notification, entry.getImportance());
+            public void onPreEntryUpdated(NotificationEntry entry) {
+                updateNotification(entry, entry.getImportance());
             }
 
             @Override
@@ -63,19 +66,18 @@
                     NotificationEntry entry,
                     NotificationVisibility visibility,
                     boolean removedByUser) {
-                removeNotification(entry.notification);
+                removeNotification(entry.getSbn());
             }
         });
 
-        notificationEntryManager.addNotificationLifetimeExtender(
-                new ForegroundServiceLifetimeExtender());
+        mEntryManager.addNotificationLifetimeExtender(new ForegroundServiceLifetimeExtender());
     }
 
     /**
-     * @param sbn notification that was just posted
+     * @param entry notification that was just posted
      */
-    private void addNotification(StatusBarNotification sbn, int importance) {
-        updateNotification(sbn, importance);
+    private void addNotification(NotificationEntry entry, int importance) {
+        updateNotification(entry, importance);
     }
 
     /**
@@ -113,9 +115,10 @@
     }
 
     /**
-     * @param sbn notification that was just changed in some way
+     * @param entry notification that was just changed in some way
      */
-    private void updateNotification(StatusBarNotification sbn, int newImportance) {
+    private void updateNotification(NotificationEntry entry, int newImportance) {
+        final StatusBarNotification sbn = entry.getSbn();
         mForegroundServiceController.updateUserState(
                 sbn.getUserId(),
                 userState -> {
@@ -143,8 +146,22 @@
                             }
                         }
                     }
+                    tagForeground(entry);
                     return true;
                 },
                 true /* create if not found */);
     }
+
+    private void tagForeground(NotificationEntry entry) {
+        final StatusBarNotification sbn = entry.getSbn();
+        ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
+                sbn.getUserId(),
+                sbn.getPackageName());
+        if (activeOps != null) {
+            synchronized (entry.mActiveAppOps) {
+                entry.mActiveAppOps.clear();
+                entry.mActiveAppOps.addAll(activeOps);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index ddbabee..30a60ab 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui;
 
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -28,21 +30,32 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.StatusBar;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
 
 /**
  * Class that only runs on debuggable builds that listens to broadcasts that simulate actions in the
  * system that are used for testing the latency.
  */
+@Singleton
 public class LatencyTester extends SystemUI {
 
-    private static final String ACTION_FINGERPRINT_WAKE =
+    private static final String
+            ACTION_FINGERPRINT_WAKE =
             "com.android.systemui.latency.ACTION_FINGERPRINT_WAKE";
-    private static final String ACTION_TURN_ON_SCREEN =
+    private static final String
+            ACTION_TURN_ON_SCREEN =
             "com.android.systemui.latency.ACTION_TURN_ON_SCREEN";
+    private final BiometricUnlockController mBiometricUnlockController;
+    private final PowerManager mPowerManager;
 
-    public LatencyTester(Context context) {
+    @Inject
+    public LatencyTester(Context context, BiometricUnlockController biometricUnlockController,
+            PowerManager powerManager) {
         super(context);
+        mBiometricUnlockController = biometricUnlockController;
+        mPowerManager = powerManager;
     }
 
     @Override
@@ -68,19 +81,17 @@
     }
 
     private void fakeTurnOnScreen() {
-        PowerManager powerManager = mContext.getSystemService(PowerManager.class);
         if (LatencyTracker.isEnabled(mContext)) {
             LatencyTracker.getInstance(mContext).onActionStart(
                     LatencyTracker.ACTION_TURN_ON_SCREEN);
         }
-        powerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:LATENCY_TESTS");
+        mPowerManager.wakeUp(
+                SystemClock.uptimeMillis(), WAKE_REASON_UNKNOWN, "android.policy:LATENCY_TESTS");
     }
 
     private void fakeWakeAndUnlock() {
-        BiometricUnlockController biometricUnlockController = getComponent(StatusBar.class)
-                .getBiometricUnlockController();
-        biometricUnlockController.onBiometricAcquired(BiometricSourceType.FINGERPRINT);
-        biometricUnlockController.onBiometricAuthenticated(
+        mBiometricUnlockController.onBiometricAcquired(BiometricSourceType.FINGERPRINT);
+        mBiometricUnlockController.onBiometricAuthenticated(
                 KeyguardUpdateMonitor.getCurrentUser(), BiometricSourceType.FINGERPRINT);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index ad20986..8a99e45 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -81,10 +81,16 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
 /**
  * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
  * for antialiasing and emulation purposes.
  */
+@Singleton
 public class ScreenDecorations extends SystemUI implements Tunable {
     private static final boolean DEBUG = false;
     private static final String TAG = "ScreenDecorations";
@@ -94,6 +100,7 @@
     private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
             SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
     private static final boolean VERBOSE = false;
+    private final Lazy<StatusBar> mStatusBarLazy;
 
     private DisplayManager mDisplayManager;
     private DisplayManager.DisplayListener mDisplayListener;
@@ -132,8 +139,10 @@
         return result;
     }
 
-    public ScreenDecorations(Context context) {
+    @Inject
+    public ScreenDecorations(Context context, Lazy<StatusBar> statusBarLazy) {
         super(context);
+        mStatusBarLazy = statusBarLazy;
     }
 
     @Override
@@ -434,13 +443,13 @@
 
     private void setupStatusBarPadding(int padding) {
         // Add some padding to all the content near the edge of the screen.
-        StatusBar sb = getComponent(StatusBar.class);
-        View statusBar = (sb != null ? sb.getStatusBarWindow() : null);
-        if (statusBar != null) {
-            TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING,
-                    padding, FLAG_END);
+        StatusBar statusBar = mStatusBarLazy.get();
+        View statusBarWindow = statusBar.getStatusBarWindow();
+        if (statusBarWindow != null) {
+            TunablePadding.addTunablePadding(statusBarWindow.findViewById(R.id.keyguard_header),
+                    PADDING, padding, FLAG_END);
 
-            FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar);
+            FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBarWindow);
             fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG,
                     new TunablePaddingTagListener(padding, R.id.status_bar));
             fragmentHostManager.addTagListener(QS.TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
index aa13fa8..746515a 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
@@ -27,6 +27,8 @@
 import androidx.annotation.Nullable;
 import androidx.core.app.AppComponentFactory;
 
+import com.android.systemui.dagger.ContextComponentHelper;
+
 import javax.inject.Inject;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 91776a3..022bf06 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -34,6 +34,7 @@
 import android.util.Log;
 import android.util.TimingsTraceLog;
 
+import com.android.systemui.dagger.ContextComponentHelper;
 import com.android.systemui.plugins.OverlayPlugin;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.shared.plugins.PluginManager;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index ef7526b..0a547b6 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -17,7 +17,6 @@
 package com.android.systemui;
 
 import android.annotation.NonNull;
-import android.app.AlarmManager;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -25,32 +24,27 @@
 import android.view.ViewGroup;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.colorextraction.ColorExtractor.GradientColors;
-import com.android.internal.util.function.TriConsumer;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.dagger.DaggerSystemUIRootComponent;
+import com.android.systemui.dagger.DependencyProvider;
+import com.android.systemui.dagger.SystemUIRootComponent;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.LockIcon;
-import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.ScrimState;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
-import java.util.function.Consumer;
-
 import dagger.Module;
 import dagger.Provides;
 
@@ -116,7 +110,7 @@
 
     protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
         return DaggerSystemUIRootComponent.builder()
-                .dependencyProvider(new com.android.systemui.DependencyProvider())
+                .dependencyProvider(new DependencyProvider())
                 .contextHolder(new ContextHolder(context))
                 .build();
     }
@@ -143,16 +137,6 @@
                 new Handler(Looper.getMainLooper()));
     }
 
-    public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
-            ScrimView scrimForBubble,
-            LockscreenWallpaper lockscreenWallpaper,
-            TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
-            Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
-            AlarmManager alarmManager, KeyguardStateController keyguardStateController) {
-        return new ScrimController(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
-                scrimVisibleListener, dozeParameters, alarmManager, keyguardStateController);
-    }
-
     public NotificationIconAreaController createNotificationIconAreaController(Context context,
             StatusBar statusBar,
             NotificationWakeUpCoordinator wakeUpCoordinator,
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 8f1fcae..3f56ff0 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui;
 
+import android.annotation.NonNull;
 import android.app.Service;
 import android.content.Intent;
 import android.os.Build;
@@ -66,7 +67,13 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (args != null && args.length > 0 && args[0].equals("--config")) {
+            dumpConfig(pw);
+            return;
+        }
+
         dumpServices(((SystemUIApplication) getApplication()).getServices(), fd, pw, args);
+        dumpConfig(pw);
     }
 
     static void dumpServices(
@@ -95,5 +102,29 @@
             }
         }
     }
+
+    private void dumpConfig(@NonNull PrintWriter pw) {
+        pw.println("SystemUiServiceComponents configuration:");
+
+        pw.print("vendor component: ");
+        pw.println(getResources().getString(R.string.config_systemUIVendorServiceComponent));
+
+        dumpConfig(pw, "global", R.array.config_systemUIServiceComponents);
+        dumpConfig(pw, "per-user", R.array.config_systemUIServiceComponentsPerUser);
+    }
+
+    private void dumpConfig(@NonNull PrintWriter pw, @NonNull String type, int resId) {
+        final String[] services = getResources().getStringArray(resId);
+        pw.print(type); pw.print(": ");
+        if (services == null) {
+            pw.println("N/A");
+            return;
+        }
+        pw.print(services.length);
+        pw.println(" services");
+        for (int i = 0; i < services.length; i++) {
+            pw.print("  "); pw.print(i); pw.print(": "); pw.println(services[i]);
+        }
+    }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index ef171d3..f616d57 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.appops;
 
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
-
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -31,6 +29,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.BgLooper;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -39,7 +38,6 @@
 import java.util.Set;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -79,7 +77,7 @@
     };
 
     @Inject
-    public AppOpsControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
+    public AppOpsControllerImpl(Context context, @BgLooper Looper bgLooper) {
         this(context, bgLooper, new PermissionFlagsCache(context));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index cdc2623..446ed25 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.biometrics;
 
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.IActivityTaskManager;
@@ -27,6 +30,8 @@
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -34,6 +39,7 @@
 import android.util.Log;
 import android.view.WindowManager;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 import com.android.systemui.SystemUI;
@@ -87,8 +93,11 @@
                         Log.w(TAG, "Evicting client due to: " + topPackage);
                         mCurrentDialog.dismissWithoutCallback(true /* animate */);
                         mCurrentDialog = null;
-                        mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
-                        mReceiver = null;
+                        if (mReceiver != null) {
+                            mReceiver.onDialogDismissed(
+                                    BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
+                            mReceiver = null;
+                        }
                     }
                 }
             } catch (RemoteException e) {
@@ -99,6 +108,10 @@
 
     @Override
     public void onTryAgainPressed() {
+        if (mReceiver == null) {
+            Log.e(TAG, "onTryAgainPressed: Receiver is null");
+            return;
+        }
         try {
             mReceiver.onTryAgainPressed();
         } catch (RemoteException e) {
@@ -108,6 +121,10 @@
 
     @Override
     public void onDeviceCredentialPressed() {
+        if (mReceiver == null) {
+            Log.e(TAG, "onDeviceCredentialPressed: Receiver is null");
+            return;
+        }
         try {
             mReceiver.onDeviceCredentialPressed();
         } catch (RemoteException e) {
@@ -155,7 +172,7 @@
 
     private void sendResultAndCleanUp(@DismissedReason int reason) {
         if (mReceiver == null) {
-            Log.e(TAG, "Receiver is null");
+            Log.e(TAG, "sendResultAndCleanUp: Receiver is null");
             return;
         }
         try {
@@ -229,15 +246,8 @@
     }
 
     @Override
-    public void onBiometricAuthenticated(boolean authenticated, String failureReason) {
-        if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: " + authenticated
-                + " reason: " + failureReason);
-
-        if (authenticated) {
-            mCurrentDialog.onAuthenticationSucceeded();
-        } else {
-            mCurrentDialog.onAuthenticationFailed(failureReason);
-        }
+    public void onBiometricAuthenticated() {
+        mCurrentDialog.onAuthenticationSucceeded();
     }
 
     @Override
@@ -247,16 +257,45 @@
         mCurrentDialog.onHelp(message);
     }
 
-    @Override
-    public void onBiometricError(int errorCode, String error) {
-        if (DEBUG) Log.d(TAG, "onBiometricError: " + errorCode + ", " + error);
+    private String getErrorString(int modality, int error, int vendorCode) {
+        switch (modality) {
+            case TYPE_FACE:
+                return FaceManager.getErrorString(mContext, error, vendorCode);
 
-        final boolean isLockout = errorCode == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
-                || errorCode == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+            case TYPE_FINGERPRINT:
+                return FingerprintManager.getErrorString(mContext, error, vendorCode);
+
+            default:
+                return "";
+        }
+    }
+
+    @Override
+    public void onBiometricError(int modality, int error, int vendorCode) {
+        if (DEBUG) {
+            Log.d(TAG, String.format("onBiometricError(%d, %d, %d)", modality, error, vendorCode));
+        }
+
+        final boolean isLockout = (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT)
+                || (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT);
+
+        // TODO(b/141025588): Create separate methods for handling hard and soft errors.
+        final boolean isSoftError = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED
+                || error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT);
+
         if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
+            if (DEBUG) Log.d(TAG, "onBiometricError, lockout");
             mCurrentDialog.animateToCredentialUI();
+        } else if (isSoftError) {
+            final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED)
+                    ? mContext.getString(R.string.biometric_not_recognized)
+                    : getErrorString(modality, error, vendorCode);
+            if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
+            mCurrentDialog.onAuthenticationFailed(errorMessage);
         } else {
-            mCurrentDialog.onError(error);
+            final String errorMessage = getErrorString(modality, error, vendorCode);
+            if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
+            mCurrentDialog.onError(errorMessage);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index 5e977b4..ff4711c 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -26,13 +26,12 @@
 import android.util.Log
 import android.util.SparseArray
 import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.Dependency.BG_LOOPER_NAME
-import com.android.systemui.Dependency.MAIN_HANDLER_NAME
 import com.android.systemui.Dumpable
+import com.android.systemui.dagger.qualifiers.BgLooper
+import com.android.systemui.dagger.qualifiers.MainHandler
 import java.io.FileDescriptor
 import java.io.PrintWriter
 import javax.inject.Inject
-import javax.inject.Named
 import javax.inject.Singleton
 
 data class ReceiverData(
@@ -61,8 +60,8 @@
 @Singleton
 open class BroadcastDispatcher @Inject constructor (
     private val context: Context,
-    @Named(MAIN_HANDLER_NAME) private val mainHandler: Handler,
-    @Named(BG_LOOPER_NAME) private val bgLooper: Looper
+    @MainHandler private val mainHandler: Handler,
+    @BgLooper private val bgLooper: Looper
 ) : Dumpable {
 
     // Only modify in BG thread
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index c3cee35..7600b2f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -83,23 +83,23 @@
     private boolean mSuppressFlyout;
 
     public static String groupId(NotificationEntry entry) {
-        UserHandle user = entry.notification.getUser();
-        return user.getIdentifier() + "|" + entry.notification.getPackageName();
+        UserHandle user = entry.getSbn().getUser();
+        return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
     }
 
     /** Used in tests when no UI is required. */
     @VisibleForTesting(visibility = PRIVATE)
     Bubble(Context context, NotificationEntry e) {
         mEntry = e;
-        mKey = e.key;
-        mLastUpdated = e.notification.getPostTime();
+        mKey = e.getKey();
+        mLastUpdated = e.getSbn().getPostTime();
         mGroupId = groupId(e);
 
         PackageManager pm = context.getPackageManager();
         ApplicationInfo info;
         try {
             info = pm.getApplicationInfo(
-                mEntry.notification.getPackageName(),
+                mEntry.getSbn().getPackageName(),
                 PackageManager.MATCH_UNINSTALLED_PACKAGES
                     | PackageManager.MATCH_DISABLED_COMPONENTS
                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
@@ -107,10 +107,10 @@
             if (info != null) {
                 mAppName = String.valueOf(pm.getApplicationLabel(info));
             }
-            Drawable appIcon = pm.getApplicationIcon(mEntry.notification.getPackageName());
-            mUserBadgedAppIcon = pm.getUserBadgedIcon(appIcon, mEntry.notification.getUser());
+            Drawable appIcon = pm.getApplicationIcon(mEntry.getSbn().getPackageName());
+            mUserBadgedAppIcon = pm.getUserBadgedIcon(appIcon, mEntry.getSbn().getUser());
         } catch (PackageManager.NameNotFoundException unused) {
-            mAppName = mEntry.notification.getPackageName();
+            mAppName = mEntry.getSbn().getPackageName();
         }
     }
 
@@ -127,7 +127,7 @@
     }
 
     public String getPackageName() {
-        return mEntry.notification.getPackageName();
+        return mEntry.getSbn().getPackageName();
     }
 
     public String getAppName() {
@@ -190,7 +190,7 @@
 
     void updateEntry(NotificationEntry entry) {
         mEntry = entry;
-        mLastUpdated = entry.notification.getPostTime();
+        mLastUpdated = entry.getSbn().getPostTime();
         if (mInflated) {
             mIconView.update(this);
             mExpandedView.update(this);
@@ -287,7 +287,7 @@
      * is an ongoing bubble.
      */
     boolean isOngoing() {
-        int flags = mEntry.notification.getNotification().flags;
+        int flags = mEntry.getSbn().getNotification().flags;
         return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
     }
 
@@ -296,8 +296,8 @@
         boolean useRes = data.getDesiredHeightResId() != 0;
         if (useRes) {
             return getDimenForPackageUser(context, data.getDesiredHeightResId(),
-                    mEntry.notification.getPackageName(),
-                    mEntry.notification.getUser().getIdentifier());
+                    mEntry.getSbn().getPackageName(),
+                    mEntry.getSbn().getUser().getIdentifier());
         } else {
             return data.getDesiredHeight()
                     * context.getResources().getDisplayMetrics().density;
@@ -316,7 +316,7 @@
 
     @Nullable
     PendingIntent getBubbleIntent(Context context) {
-        Notification notif = mEntry.notification.getNotification();
+        Notification notif = mEntry.getSbn().getNotification();
         Notification.BubbleMetadata data = notif.getBubbleMetadata();
         if (BubbleController.canLaunchInActivityView(context, mEntry) && data != null) {
             return data.getIntent();
@@ -327,7 +327,7 @@
     Intent getSettingsIntent() {
         final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
         intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
-        intent.putExtra(Settings.EXTRA_APP_UID, mEntry.notification.getUid());
+        intent.putExtra(Settings.EXTRA_APP_UID, mEntry.getSbn().getUid());
         intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
@@ -339,7 +339,7 @@
      * notification, based on its type. Returns null if there should not be an update message.
      */
     CharSequence getUpdateMessage(Context context) {
-        final Notification underlyingNotif = mEntry.notification.getNotification();
+        final Notification underlyingNotif = mEntry.getSbn().getNotification();
         final Class<? extends Notification.Style> style = underlyingNotif.getNotificationStyle();
 
         try {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 9568a18..0231b56 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -262,7 +262,7 @@
                         // More notifications could be added causing summary to no longer
                         // be suppressed -- in this case need to remove the key.
                         final String groupKey = group.summary != null
-                                ? group.summary.notification.getGroupKey()
+                                ? group.summary.getSbn().getGroupKey()
                                 : null;
                         if (!suppressed && groupKey != null
                                 && mBubbleData.isSummarySuppressed(groupKey)) {
@@ -346,7 +346,7 @@
             return;
         }
         for (NotificationEntry e : notificationData.getNotificationsForCurrentUser()) {
-            if (savedBubbleKeys.contains(e.key)
+            if (savedBubbleKeys.contains(e.getKey())
                     && mNotificationInterruptionStateProvider.shouldBubbleUp(e)
                     && canLaunchInActivityView(mContext, e)) {
                 updateBubble(e, /* suppressFlyout= */ true);
@@ -445,7 +445,7 @@
         boolean isBubbleAndSuppressed = mBubbleData.hasBubbleWithKey(key)
                 && !mBubbleData.getBubbleWithKey(key).showInShadeWhenBubble();
         NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
-        String groupKey = entry != null ? entry.notification.getGroupKey() : null;
+        String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
         boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey);
         boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey));
         return (isSummary && isSuppressedSummary) || isBubbleAndSuppressed;
@@ -528,14 +528,14 @@
             @Override
             public boolean onNotificationRemoveRequested(String key, int reason) {
                 NotificationEntry entry = mNotificationEntryManager.getNotificationData().get(key);
-                String groupKey = entry != null ? entry.notification.getGroupKey() : null;
+                String groupKey = entry != null ? entry.getSbn().getGroupKey() : null;
                 ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
 
                 boolean inBubbleData = mBubbleData.hasBubbleWithKey(key);
                 boolean isSuppressedSummary = (mBubbleData.isSummarySuppressed(groupKey)
                         && mBubbleData.getSummaryKey(groupKey).equals(key));
                 boolean isSummary = entry != null
-                        && entry.notification.getNotification().isGroupSummary();
+                        && entry.getSbn().getNotification().isGroupSummary();
                 boolean isSummaryOfBubbles = (isSuppressedSummary || isSummary)
                         && bubbleChildren != null && !bubbleChildren.isEmpty();
 
@@ -566,7 +566,7 @@
                     bubble.setShowInShadeWhenBubble(false);
                     bubble.setShowBubbleDot(false);
                     if (mStackView != null) {
-                        mStackView.updateDotVisibility(entry.key);
+                        mStackView.updateDotVisibility(entry.getKey());
                     }
                     mNotificationEntryManager.updateNotifications(
                             "BubbleController.onNotificationRemoveRequested");
@@ -582,7 +582,7 @@
 
     private boolean handleSummaryRemovalInterception(NotificationEntry summary,
             boolean userRemovedNotif) {
-        String groupKey = summary.notification.getGroupKey();
+        String groupKey = summary.getSbn().getGroupKey();
         ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
 
         if (userRemovedNotif) {
@@ -603,11 +603,11 @@
 
             // If the summary was auto-generated we don't need to keep that notification around
             // because apps can't cancel it; so we only intercept & suppress real summaries.
-            boolean isAutogroupSummary = (summary.notification.getNotification().flags
+            boolean isAutogroupSummary = (summary.getSbn().getNotification().flags
                     & FLAG_AUTOGROUP_SUMMARY) != 0;
             if (!isAutogroupSummary) {
-                mBubbleData.addSummaryToSuppress(summary.notification.getGroupKey(),
-                        summary.key);
+                mBubbleData.addSummaryToSuppress(summary.getSbn().getGroupKey(),
+                        summary.getKey());
                 // Tell shade to update for the suppression
                 mNotificationEntryManager.updateNotifications(
                         "BubbleController.handleSummaryRemovalInterception");
@@ -641,11 +641,11 @@
         public void onPreEntryUpdated(NotificationEntry entry) {
             boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
                     && canLaunchInActivityView(mContext, entry);
-            if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
+            if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.getKey())) {
                 // It was previously a bubble but no longer a bubble -- lets remove it
-                removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
+                removeBubble(entry.getKey(), DISMISS_NO_LONGER_BUBBLE);
             } else if (shouldBubble) {
-                Bubble b = mBubbleData.getBubbleWithKey(entry.key);
+                Bubble b = mBubbleData.getBubbleWithKey(entry.getKey());
                 updateBubble(entry);
             }
         }
@@ -695,10 +695,10 @@
                             && !bubble.showInShadeWhenBubble()) {
                         // The bubble is gone & the notification is gone, time to actually remove it
                         mNotificationEntryManager.performRemoveNotification(
-                                bubble.getEntry().notification, UNDEFINED_DISMISS_REASON);
+                                bubble.getEntry().getSbn(), UNDEFINED_DISMISS_REASON);
                     } else {
                         // Update the flag for SysUI
-                        bubble.getEntry().notification.getNotification().flags &= ~FLAG_BUBBLE;
+                        bubble.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
 
                         // Make sure NoMan knows it's not a bubble anymore so anyone querying it
                         // will get right result back
@@ -712,7 +712,7 @@
 
                     // Check if removed bubble has an associated suppressed group summary that needs
                     // to be removed now.
-                    final String groupKey = bubble.getEntry().notification.getGroupKey();
+                    final String groupKey = bubble.getEntry().getSbn().getGroupKey();
                     if (mBubbleData.isSummarySuppressed(groupKey)
                             && mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
                         // Time to actually remove the summary.
@@ -721,20 +721,21 @@
                         NotificationEntry entry =
                                 mNotificationEntryManager.getNotificationData().get(notifKey);
                         mNotificationEntryManager.performRemoveNotification(
-                                entry.notification, UNDEFINED_DISMISS_REASON);
+                                entry.getSbn(), UNDEFINED_DISMISS_REASON);
                     }
 
                     // Check if summary should be removed from NoManGroup
                     NotificationEntry summary = mNotificationGroupManager.getLogicalGroupSummary(
-                            bubble.getEntry().notification);
+                            bubble.getEntry().getSbn());
                     if (summary != null) {
                         ArrayList<NotificationEntry> summaryChildren =
-                                mNotificationGroupManager.getLogicalChildren(summary.notification);
-                        boolean isSummaryThisNotif = summary.key.equals(bubble.getEntry().key);
+                                mNotificationGroupManager.getLogicalChildren(summary.getSbn());
+                        boolean isSummaryThisNotif = summary.getKey().equals(
+                                bubble.getEntry().getKey());
                         if (!isSummaryThisNotif
                                 && (summaryChildren == null || summaryChildren.isEmpty())) {
                             mNotificationEntryManager.performRemoveNotification(
-                                    summary.notification, UNDEFINED_DISMISS_REASON);
+                                    summary.getSbn(), UNDEFINED_DISMISS_REASON);
                         }
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index d43e030..4e229c0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -183,8 +183,8 @@
         if (DEBUG_BUBBLE_DATA) {
             Log.d(TAG, "notificationEntryUpdated: " + entry);
         }
-        Bubble bubble = getBubbleWithKey(entry.key);
-        suppressFlyout = !entry.isVisuallyInterruptive || suppressFlyout;
+        Bubble bubble = getBubbleWithKey(entry.getKey());
+        suppressFlyout = !entry.getRanking().visuallyInterruptive() || suppressFlyout;
 
         if (bubble == null) {
             // Create a new bubble
@@ -217,7 +217,7 @@
         if (DEBUG_BUBBLE_DATA) {
             Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason);
         }
-        doRemove(entry.key, reason);
+        doRemove(entry.getKey(), reason);
         dispatchPendingChanges();
     }
 
@@ -290,7 +290,7 @@
             return bubbleChildren;
         }
         for (Bubble b : mBubbles) {
-            if (groupKey.equals(b.getEntry().notification.getGroupKey())) {
+            if (groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
                 bubbleChildren.add(b);
             }
         }
@@ -633,7 +633,8 @@
                 try {
                     deleteIntent.send();
                 } catch (PendingIntent.CanceledException e) {
-                    Log.w(TAG, "Failed to send delete intent for bubble with key: " + entry.key);
+                    Log.w(TAG, "Failed to send delete intent for bubble with key: "
+                            + entry.getKey());
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 6f953d5..1d9f6b2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -501,7 +501,7 @@
         if (id == R.id.settings_button) {
             Intent intent = mBubble.getSettingsIntent();
             mStackView.collapseStack(() -> {
-                mContext.startActivityAsUser(intent, mBubble.getEntry().notification.getUser());
+                mContext.startActivityAsUser(intent, mBubble.getEntry().getSbn().getUser());
                 logBubbleClickEvent(mBubble,
                         StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
             });
@@ -609,7 +609,7 @@
      * @param action the user interaction enum.
      */
     private void logBubbleClickEvent(Bubble bubble, int action) {
-        StatusBarNotification notification = bubble.getEntry().notification;
+        StatusBarNotification notification = bubble.getEntry().getSbn();
         StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
                 notification.getPackageName(),
                 notification.getNotification().getChannelId(),
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 340dced..e5af389 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -629,7 +629,7 @@
         }
         Bubble topBubble = mBubbleData.getBubbles().get(0);
         String appName = topBubble.getAppName();
-        Notification notification = topBubble.getEntry().notification.getNotification();
+        Notification notification = topBubble.getEntry().getSbn().getNotification();
         CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
         String titleStr = getResources().getString(R.string.stream_notification);
         if (titleCharSeq != null) {
@@ -1681,7 +1681,7 @@
      */
     private void logBubbleEvent(@Nullable Bubble bubble, int action) {
         if (bubble == null || bubble.getEntry() == null
-                || bubble.getEntry().notification == null) {
+                || bubble.getEntry().getSbn() == null) {
             StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
                     null /* package name */,
                     null /* notification channel */,
@@ -1695,7 +1695,7 @@
                     false /* on-going bubble */,
                     false /* isAppForeground (unused) */);
         } else {
-            StatusBarNotification notification = bubble.getEntry().notification;
+            StatusBarNotification notification = bubble.getEntry().getSbn();
             StatsLog.write(StatsLog.BUBBLE_UI_CHANGED,
                     notification.getPackageName(),
                     notification.getNotification().getChannelId(),
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 4512aa8..fe4fa90 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -39,7 +39,6 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * A floating object on the screen that can post message updates.
@@ -141,15 +140,6 @@
         mUserBadgedAppIcon = appIcon;
     }
 
-    /**
-     * @return the {@link ExpandableNotificationRow} view to display notification content when the
-     * bubble is expanded.
-     */
-    @Nullable
-    public ExpandableNotificationRow getRowView() {
-        return (mBubble != null) ? mBubble.getEntry().getRow() : null;
-    }
-
     /** Changes the dot's visibility to match the bubble view's state. */
     void updateDotVisibility(boolean animate) {
         updateDotVisibility(animate, null /* after */);
@@ -230,7 +220,7 @@
         }
         // Update icon.
         Notification.BubbleMetadata metadata = mBubble.getEntry().getBubbleMetadata();
-        Notification n = mBubble.getEntry().notification.getNotification();
+        Notification n = mBubble.getEntry().getSbn().getNotification();
         Icon ic = metadata.getIcon();
         boolean needsTint = ic.getType() != Icon.TYPE_ADAPTIVE_BITMAP;
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 914258f..db85fa0 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -17,7 +17,6 @@
 package com.android.systemui.classifier;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_MANAGER_ENABLED;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
 
 import android.content.Context;
 import android.hardware.SensorManager;
@@ -31,6 +30,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
 import com.android.systemui.classifier.brightline.FalsingDataProvider;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.FalsingPlugin;
 import com.android.systemui.plugins.PluginListener;
@@ -41,7 +41,6 @@
 import java.io.PrintWriter;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -62,7 +61,7 @@
 
     @Inject
     FalsingManagerProxy(Context context, PluginManager pluginManager,
-            @Named(MAIN_HANDLER_NAME) Handler handler,
+            @MainHandler Handler handler,
             ProximitySensor proximitySensor,
             DeviceConfigProxy deviceConfig) {
         mProximitySensor = proximitySensor;
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/ActivityBinder.java
rename to packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java
index 2c8a672..4be610f 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import android.app.Activity;
 
+import com.android.systemui.ForegroundServicesDialog;
 import com.android.systemui.tuner.TunerActivity;
 
 import dagger.Binds;
diff --git a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/ComponentBinder.java
rename to packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
index 3b35c61..4e4c06e 100644
--- a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import dagger.Binds;
 import dagger.Module;
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java
rename to packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
index 2cf0f8d..d6d1e41 100644
--- a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import android.app.Activity;
 import android.app.Service;
 
+import com.android.systemui.SystemUI;
+
 /**
  * Interface necessary to make Dagger happy. See {@link ContextComponentResolver}.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java
rename to packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
index 9952632..d7822c9 100644
--- a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import android.app.Activity;
 import android.app.Service;
 
+import com.android.systemui.SystemUI;
+
 import java.util.Map;
 
 import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/DependencyBinder.java
rename to packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
index f9f0f1b..9032c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyBinder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
+import com.android.systemui.ActivityStarterDelegate;
 import com.android.systemui.appops.AppOpsController;
 import com.android.systemui.appops.AppOpsControllerImpl;
 import com.android.systemui.classifier.FalsingManagerProxy;
+import com.android.systemui.doze.DozeHost;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.FalsingManager;
@@ -32,6 +34,7 @@
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -240,5 +243,10 @@
     /**
      */
     @Binds
-    public abstract FalsingManager provideFalsingmanager(FalsingManagerProxy falsingManagerImpl);
+    public abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
+
+    /**
+     */
+    @Binds
+    public abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
similarity index 65%
rename from packages/SystemUI/src/com/android/systemui/DependencyProvider.java
rename to packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 9192eed..87434f3 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,50 +14,35 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
-import static com.android.systemui.Dependency.BG_HANDLER_NAME;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
 import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
 
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.AlarmManager;
-import android.app.IActivityManager;
 import android.app.INotificationManager;
-import android.app.IWallpaperManager;
 import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.SensorPrivacyManager;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.hardware.display.NightDisplayListener;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
-import android.os.PowerManager;
 import android.os.Process;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.view.IWindowManager;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
 
 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.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.MainLooper;
 import com.android.systemui.doze.AlwaysOnDisplayPolicy;
 import com.android.systemui.plugins.PluginInitializerImpl;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
-import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.phone.AutoHideController;
@@ -69,11 +54,7 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.util.leak.LeakDetector;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
 import javax.inject.Named;
-import javax.inject.Qualifier;
 import javax.inject.Singleton;
 
 import dagger.Module;
@@ -81,21 +62,19 @@
 
 /**
  * Provides dependencies for the root component of sysui injection.
+ *
+ * Only SystemUI owned classes and instances should go in here. Other, framework-owned classes
+ * should go in {@link SystemServicesModule}.
+ *
  * See SystemUI/docs/dagger.md
  */
 @Module
 public class DependencyProvider {
-    @Qualifier
-    @Documented
-    @Retention(RUNTIME)
-    public @interface MainResources {
-        // TODO: use attribute to get other, non-main resources?
-    }
 
     @Singleton
     @Provides
     @Named(TIME_TICK_HANDLER_NAME)
-    public Handler provideHandler() {
+    public Handler provideTimeTickHandler() {
         HandlerThread thread = new HandlerThread("TimeTick");
         thread.start();
         return new Handler(thread.getLooper());
@@ -103,7 +82,7 @@
 
     @Singleton
     @Provides
-    @Named(BG_LOOPER_NAME)
+    @BgLooper
     public Looper provideBgLooper() {
         HandlerThread thread = new HandlerThread("SysUiBg",
                 Process.THREAD_PRIORITY_BACKGROUND);
@@ -112,27 +91,38 @@
     }
 
     /** Main Looper */
-    @Singleton
     @Provides
-    @Named(MAIN_LOOPER_NAME)
+    @MainLooper
     public Looper provideMainLooper() {
         return Looper.getMainLooper();
     }
 
     @Singleton
     @Provides
-    @Named(BG_HANDLER_NAME)
-    public Handler provideBgHandler(@Named(BG_LOOPER_NAME) Looper bgLooper) {
+    @BgHandler
+    public Handler provideBgHandler(@BgLooper Looper bgLooper) {
         return new Handler(bgLooper);
     }
 
     @Singleton
     @Provides
-    @Named(MAIN_HANDLER_NAME)
-    public Handler provideMainHandler(@Named(MAIN_LOOPER_NAME) Looper mainLooper) {
+    @MainHandler
+    public Handler provideMainHandler(@MainLooper Looper mainLooper) {
         return new Handler(mainLooper);
     }
 
+    /** */
+    @Provides
+    public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) {
+        return new AmbientDisplayConfiguration(context);
+    }
+
+    /** */
+    @Provides
+    public Handler provideHandler() {
+        return new Handler();
+    }
+
     @Singleton
     @Provides
     public DataSaverController provideDataSaverController(NetworkController networkController) {
@@ -141,23 +131,10 @@
 
     @Singleton
     @Provides
-    @Nullable
-    public LocalBluetoothManager provideLocalBluetoothController(Context context,
-            @Named(BG_HANDLER_NAME) Handler bgHandler) {
-        return LocalBluetoothManager.create(context, bgHandler,
-                UserHandle.ALL);
-    }
-
-    @Singleton
-    @Provides
-    public MetricsLogger provideMetricsLogger() {
-        return new MetricsLogger();
-    }
-
-    @Singleton
-    @Provides
-    public IWindowManager provideIWindowManager() {
-        return WindowManagerGlobal.getWindowManagerService();
+    // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
+    // anywhere it is needed.
+    public DisplayMetrics provideDisplayMetrics() {
+        return new DisplayMetrics();
     }
 
     @Singleton
@@ -177,20 +154,6 @@
 
     @Singleton
     @Provides
-    // Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
-    // anywhere it is needed.
-    public DisplayMetrics provideDisplayMetrics() {
-        return new DisplayMetrics();
-    }
-
-    @Singleton
-    @Provides
-    public SensorPrivacyManager provideSensorPrivacyManager(Context context) {
-        return context.getSystemService(SensorPrivacyManager.class);
-    }
-
-    @Singleton
-    @Provides
     public LeakDetector provideLeakDetector() {
         return LeakDetector.create();
 
@@ -198,8 +161,14 @@
 
     @Singleton
     @Provides
+    public MetricsLogger provideMetricsLogger() {
+        return new MetricsLogger();
+    }
+
+    @Singleton
+    @Provides
     public NightDisplayListener provideNightDisplayListener(Context context,
-            @Named(BG_HANDLER_NAME) Handler bgHandler) {
+            @BgHandler Handler bgHandler) {
         return new NightDisplayListener(context, bgHandler);
     }
 
@@ -212,7 +181,7 @@
     @Singleton
     @Provides
     public NavigationBarController provideNavigationBarController(Context context,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+            @MainHandler Handler mainHandler) {
         return new NavigationBarController(context, mainHandler);
     }
 
@@ -225,7 +194,7 @@
     @Singleton
     @Provides
     public AutoHideController provideAutoHideController(Context context,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler,
+            @MainHandler Handler mainHandler,
             NotificationRemoteInputManager notificationRemoteInputManager,
             IWindowManager iWindowManager) {
         return new AutoHideController(context, mainHandler, notificationRemoteInputManager,
@@ -246,25 +215,12 @@
 
     @Singleton
     @Provides
-    public PackageManagerWrapper providePackageManagerWrapper() {
-        return PackageManagerWrapper.getInstance();
-    }
-
-    @Singleton
-    @Provides
     public DeviceProvisionedController provideDeviceProvisionedController(Context context,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+            @MainHandler Handler mainHandler) {
         return new DeviceProvisionedControllerImpl(context, mainHandler);
     }
 
     /** */
-    @Singleton
-    @Provides
-    public AlarmManager provideAlarmManager(Context context) {
-        return context.getSystemService(AlarmManager.class);
-    }
-
-    /** */
     @Provides
     public LockPatternUtils provideLockPatternUtils(Context context) {
         return new LockPatternUtils(context);
@@ -272,45 +228,7 @@
 
     /** */
     @Provides
-    public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) {
-        return new AmbientDisplayConfiguration(context);
-    }
-
-    /** */
-    @Provides
     public AlwaysOnDisplayPolicy provideAlwaysOnDisplayPolicy(Context context) {
         return new AlwaysOnDisplayPolicy(context);
     }
-
-    /** */
-    @Provides
-    public PowerManager providePowerManager(Context context) {
-        return context.getSystemService(PowerManager.class);
-    }
-
-    /** */
-    @Provides
-    @MainResources
-    public Resources provideResources(Context context) {
-        return context.getResources();
-    }
-
-    /** */
-    @Provides
-    public IWallpaperManager provideWallPaperManager() {
-        return IWallpaperManager.Stub.asInterface(
-                ServiceManager.getService(Context.WALLPAPER_SERVICE));
-    }
-
-    /** */
-    @Provides
-    public WindowManager providesWindowManager(Context context) {
-        return context.getSystemService(WindowManager.class);
-    }
-
-    /** */
-    @Provides
-    public IActivityManager providesIActivityManager() {
-        return ActivityManager.getService();
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/ServiceBinder.java
rename to packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java
index c11236e..1f2c0a1 100644
--- a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import android.app.Service;
 
+import com.android.systemui.ImageWallpaper;
 import com.android.systemui.doze.DozeService;
 import com.android.systemui.keyguard.KeyguardService;
 
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
new file mode 100644
index 0000000..fffba8c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -0,0 +1,130 @@
+/*
+ * 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.systemui.dagger;
+
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.IActivityManager;
+import android.app.IWallpaperManager;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.hardware.SensorPrivacyManager;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.view.IWindowManager;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+
+import com.android.internal.util.LatencyTracker;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.shared.system.PackageManagerWrapper;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Provides Non-SystemUI, Framework-Owned instances to the dependency graph.
+ */
+@Module
+public class SystemServicesModule {
+
+    @Singleton
+    @Provides
+    static AlarmManager provideAlarmManager(Context context) {
+        return context.getSystemService(AlarmManager.class);
+    }
+
+    @Singleton
+    @Provides
+    static IActivityManager provideIActivityManager() {
+        return ActivityManager.getService();
+    }
+
+    @Provides
+    @Nullable
+    static IWallpaperManager provideIWallPaperManager() {
+        return IWallpaperManager.Stub.asInterface(
+                ServiceManager.getService(Context.WALLPAPER_SERVICE));
+    }
+
+    @Singleton
+    @Provides
+    static IWindowManager provideIWindowManager() {
+        return WindowManagerGlobal.getWindowManagerService();
+    }
+
+    @Singleton
+    @Provides
+    static LatencyTracker provideLatencyTracker(Context context) {
+        return LatencyTracker.getInstance(context);
+    }
+
+    @SuppressLint("MissingPermission")
+    @Singleton
+    @Provides
+    @Nullable
+    static LocalBluetoothManager provideLocalBluetoothController(Context context,
+            @BgHandler Handler bgHandler) {
+        return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL);
+    }
+
+    @Singleton
+    @Provides
+    static PackageManagerWrapper providePackageManagerWrapper() {
+        return PackageManagerWrapper.getInstance();
+    }
+
+    /** */
+    @Singleton
+    @Provides
+    static PowerManager providePowerManager(Context context) {
+        return context.getSystemService(PowerManager.class);
+    }
+
+    @Provides
+    @MainResources
+    static Resources provideResources(Context context) {
+        return context.getResources();
+    }
+
+    @Singleton
+    @Provides
+    static SensorPrivacyManager provideSensorPrivacyManager(Context context) {
+        return context.getSystemService(SensorPrivacyManager.class);
+    }
+
+    @Provides
+    static WallpaperManager provideWallpaperManager(Context context) {
+        return (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
+    }
+
+    @Singleton
+    @Provides
+    static WindowManager provideWindowManager(Context context) {
+        return context.getSystemService(WindowManager.class);
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
similarity index 80%
rename from packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
rename to packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index a5a5598..738f539 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
+import com.android.systemui.LatencyTester;
+import com.android.systemui.ScreenDecorations;
+import com.android.systemui.SystemUI;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.pip.PipUI;
 import com.android.systemui.power.PowerUI;
@@ -47,6 +50,12 @@
     @ClassKey(KeyguardViewMediator.class)
     public abstract SystemUI bindKeyguardViewMediator(KeyguardViewMediator sysui);
 
+    /** Inject into LatencyTests. */
+    @Binds
+    @IntoMap
+    @ClassKey(LatencyTester.class)
+    public abstract SystemUI bindLatencyTester(LatencyTester sysui);
+
     /** Inject into PipUI. */
     @Binds
     @IntoMap
@@ -65,6 +74,12 @@
     @ClassKey(Recents.class)
     public abstract SystemUI bindRecents(Recents sysui);
 
+    /** Inject into ScreenDecorations. */
+    @Binds
+    @IntoMap
+    @ClassKey(ScreenDecorations.class)
+    public abstract SystemUI bindScreenDecorations(ScreenDecorations sysui);
+
     /** Inject into VolumeUI. */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
rename to packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 176bcbf..c95b50b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
 import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
 
 import androidx.annotation.Nullable;
 
+import com.android.systemui.SystemUI;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dock.DockManagerImpl;
 import com.android.systemui.power.EnhancedEstimates;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
similarity index 79%
rename from packages/SystemUI/src/com/android/systemui/SystemUIModule.java
rename to packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index b0316e22..4e60f19 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageManager;
 
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.assist.AssistModule;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.people.PeopleHubModule;
 import com.android.systemui.statusbar.phone.KeyguardLiftController;
 import com.android.systemui.util.sensors.AsyncSensorManager;
 
@@ -35,7 +37,9 @@
  * A dagger module for injecting components of System UI that are not overridden by the System UI
  * implementation.
  */
-@Module(includes = {AssistModule.class, ComponentBinder.class})
+@Module(includes = {AssistModule.class,
+                    ComponentBinder.class,
+                    PeopleHubModule.class})
 public abstract class SystemUIModule {
 
     @Singleton
@@ -43,11 +47,13 @@
     @Nullable
     static KeyguardLiftController provideKeyguardLiftController(Context context,
             StatusBarStateController statusBarStateController,
-            AsyncSensorManager asyncSensorManager) {
+            AsyncSensorManager asyncSensorManager,
+            KeyguardUpdateMonitor keyguardUpdateMonitor) {
         if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
             return null;
         }
-        return new KeyguardLiftController(statusBarStateController, asyncSensorManager);
+        return new KeyguardLiftController(statusBarStateController, asyncSensorManager,
+                keyguardUpdateMonitor);
     }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
similarity index 91%
rename from packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
rename to packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
index bcbe672..113c9c8 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger;
 
 import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
 
 import android.content.ContentProvider;
 
+import com.android.systemui.Dependency;
+import com.android.systemui.SystemUIAppComponentFactory;
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.InjectionInflationController;
@@ -36,6 +39,7 @@
 @Component(modules = {
         DependencyProvider.class,
         DependencyBinder.class,
+        SystemServicesModule.class,
         SystemUIFactory.ContextHolder.class,
         SystemUIModule.class,
         SystemUIDefaultModule.class})
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java
similarity index 61%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java
index d2ec357..bc6b83b 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,17 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package com.android.systemui.dagger.qualifiers;
 
-parcelable TimeSignal;
\ No newline at end of file
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface BgHandler {
+}
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java
similarity index 61%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java
index d2ec357..2aadda1 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,17 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package com.android.systemui.dagger.qualifiers;
 
-parcelable TimeSignal;
\ No newline at end of file
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface BgLooper {
+}
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java
similarity index 61%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java
index d2ec357..79661fa 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,17 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package com.android.systemui.dagger.qualifiers;
 
-parcelable TimeSignal;
\ No newline at end of file
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface MainHandler {
+}
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java
similarity index 61%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java
index d2ec357..750d7d7 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,17 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package com.android.systemui.dagger.qualifiers;
 
-parcelable TimeSignal;
\ No newline at end of file
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface MainLooper {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
similarity index 60%
copy from packages/SystemUI/src/com/android/systemui/ComponentBinder.java
copy to packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
index 3b35c61..3daeda5 100644
--- a/packages/SystemUI/src/com/android/systemui/ComponentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.systemui;
+package com.android.systemui.dagger.qualifiers;
 
-import dagger.Binds;
-import dagger.Module;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
-/**
- * Dagger Module that collects related sub-modules together.
- */
-@Module(includes = {ActivityBinder.class, ServiceBinder.class, SystemUIBinder.class})
-public abstract class ComponentBinder {
-    /** */
-    @Binds
-    public abstract ContextComponentHelper bindComponentHelper(
-            ContextComponentResolver componentHelper);
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface MainResources {
+    // TODO: use attribute to get other, non-main resources?
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 3f0505f..33f68cf 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.doze;
 
+import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.Application;
 import android.app.IWallpaperManager;
@@ -53,13 +54,20 @@
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final DockManager mDockManager;
     private final IWallpaperManager mWallpaperManager;
+    private final ProximitySensor mProximitySensor;
+    private final DelayedWakeLock.Builder mDelayedWakeLockBuilder;
+    private final Handler mHandler;
+    private final BiometricUnlockController mBiometricUnlockController;
 
     @Inject
     public DozeFactory(FalsingManager falsingManager, DozeLog dozeLog,
             DozeParameters dozeParameters, BatteryController batteryController,
             AsyncSensorManager asyncSensorManager, AlarmManager alarmManager,
             WakefulnessLifecycle wakefulnessLifecycle, KeyguardUpdateMonitor keyguardUpdateMonitor,
-            DockManager dockManager, IWallpaperManager wallpaperManager) {
+            DockManager dockManager, @Nullable IWallpaperManager wallpaperManager,
+            ProximitySensor proximitySensor,
+            DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
+            BiometricUnlockController biometricUnlockController) {
         mFalsingManager = falsingManager;
         mDozeLog = dozeLog;
         mDozeParameters = dozeParameters;
@@ -70,15 +78,17 @@
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mDockManager = dockManager;
         mWallpaperManager = wallpaperManager;
+        mProximitySensor = proximitySensor;
+        mDelayedWakeLockBuilder = delayedWakeLockBuilder;
+        mHandler = handler;
+        mBiometricUnlockController = biometricUnlockController;
     }
 
     /** Creates a DozeMachine with its parts for {@code dozeService}. */
-    public DozeMachine assembleMachine(DozeService dozeService) {
+    DozeMachine assembleMachine(DozeService dozeService) {
         DozeHost host = getHost(dozeService);
         AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(dozeService);
-        Handler handler = new Handler();
-        WakeLock wakeLock = new DelayedWakeLock(handler,
-                WakeLock.createPartial(dozeService, "Doze"));
+        WakeLock wakeLock = mDelayedWakeLockBuilder.setHandler(mHandler).setTag("Doze").build();
 
         DozeMachine.Service wrappedService = dozeService;
         wrappedService = new DozeBrightnessHostForwarder(wrappedService, host);
@@ -90,20 +100,18 @@
         DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock,
                                               mWakefulnessLifecycle, mBatteryController, mDozeLog);
         machine.setParts(new DozeMachine.Part[]{
-                new DozePauser(handler, machine, mAlarmManager, mDozeParameters.getPolicy()),
+                new DozePauser(mHandler, machine, mAlarmManager, mDozeParameters.getPolicy()),
                 new DozeFalsingManagerAdapter(mFalsingManager),
                 createDozeTriggers(dozeService, mAsyncSensorManager, host, mAlarmManager, config,
-                        mDozeParameters, handler, wakeLock, machine, mDockManager, mDozeLog),
-                createDozeUi(dozeService, host, wakeLock, machine, handler, mAlarmManager,
+                        mDozeParameters, mHandler, wakeLock, machine, mDockManager, mDozeLog),
+                createDozeUi(dozeService, host, wakeLock, machine, mHandler, mAlarmManager,
                         mDozeParameters, mDozeLog),
-                new DozeScreenState(wrappedService, handler, host, mDozeParameters, wakeLock),
+                new DozeScreenState(wrappedService, mHandler, host, mDozeParameters, wakeLock),
                 createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager, host,
-                        mDozeParameters, handler),
+                        mDozeParameters, mHandler),
                 new DozeWallpaperState(
-                        mWallpaperManager,
-                        getBiometricUnlockController(dozeService),
-                        mDozeParameters),
-                new DozeDockHandler(dozeService, machine, host, config, handler, mDockManager),
+                        mWallpaperManager, mBiometricUnlockController, mDozeParameters),
+                new DozeDockHandler(dozeService, machine, host, config, mHandler, mDockManager),
                 new DozeAuthRemover(dozeService)
         });
 
@@ -126,7 +134,7 @@
         boolean allowPulseTriggers = true;
         return new DozeTriggers(context, machine, host, alarmManager, config, params,
                 sensorManager, handler, wakeLock, allowPulseTriggers, dockManager,
-                new ProximitySensor(context, sensorManager), dozeLog);
+                mProximitySensor, dozeLog);
 
     }
 
@@ -142,10 +150,4 @@
         final SystemUIApplication app = (SystemUIApplication) appCandidate;
         return app.getComponent(DozeHost.class);
     }
-
-    public static BiometricUnlockController getBiometricUnlockController(DozeService service) {
-        Application appCandidate = service.getApplication();
-        final SystemUIApplication app = (SystemUIApplication) appCandidate;
-        return app.getComponent(BiometricUnlockController.class);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 1a6bd60..d1047e2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -68,6 +68,12 @@
      */
     void prepareForGentleSleep(Runnable onDisplayOffCallback);
 
+    /**
+     * Cancel pending {@code onDisplayOffCallback} callback.
+     * @see #prepareForGentleSleep(Runnable)
+     */
+    void cancelGentleSleep();
+
     void onIgnoreTouchWhilePulsing(boolean ignore);
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 95c42fc..e1b4f31 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -71,7 +71,7 @@
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         int screenState = newState.screenState(mParameters);
-        mDozeHost.prepareForGentleSleep(null);
+        mDozeHost.cancelGentleSleep();
 
         if (newState == DozeMachine.State.FINISH) {
             // Make sure not to apply the screen state after DozeService was destroyed.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 7d86028..05a234f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -153,7 +153,7 @@
                         dozeLog),
         };
 
-        mProximitySensor = new ProximitySensor(context, sensorManager);
+        mProximitySensor = new ProximitySensor(context.getResources(), sensorManager);
 
         mProximitySensor.register(
                 proximityEvent -> {
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index b4cc571..1b4857e 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -22,7 +22,7 @@
 
 import com.android.systemui.ConfigurationChangedReceiver;
 import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUIRootComponent;
+import com.android.systemui.dagger.SystemUIRootComponent;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.statusbar.phone.NavigationBarFragment;
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 1d2de60..e66a9fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -60,7 +60,6 @@
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
 import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
 import com.android.systemui.util.wakelock.SettableWakeLock;
 import com.android.systemui.util.wakelock.WakeLock;
 
@@ -107,8 +106,8 @@
     protected final Uri mMediaUri;
     private final Date mCurrentTime = new Date();
     private final Handler mHandler;
+    private final Handler mMediaHandler;
     private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
-    private final Object mMediaToken = new Object();
     private DozeParameters mDozeParameters;
     @VisibleForTesting
     protected SettableWakeLock mMediaWakeLock;
@@ -174,17 +173,13 @@
                 }
             };
 
-    public KeyguardSliceProvider() {
-        this(new Handler());
-    }
-
     public static KeyguardSliceProvider getAttachedInstance() {
         return KeyguardSliceProvider.sInstance;
     }
 
-    @VisibleForTesting
-    KeyguardSliceProvider(Handler handler) {
-        mHandler = handler;
+    public KeyguardSliceProvider() {
+        mHandler = new Handler();
+        mMediaHandler = new Handler();
         mSliceUri = Uri.parse(KEYGUARD_SLICE_URI);
         mHeaderUri = Uri.parse(KEYGUARD_HEADER_URI);
         mDateUri = Uri.parse(KEYGUARD_DATE_URI);
@@ -328,7 +323,7 @@
             mContentResolver = getContext().getContentResolver();
             mNextAlarmController = new NextAlarmControllerImpl(getContext());
             mNextAlarmController.addCallback(this);
-            mZenModeController = new ZenModeControllerImpl(getContext(), mHandler);
+            mZenModeController = Dependency.get(ZenModeController.class);
             mZenModeController.addCallback(this);
             mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
             mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
@@ -470,16 +465,18 @@
     public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
         synchronized (this) {
             boolean nextVisible = NotificationMediaManager.isPlayingState(state);
-            mHandler.removeCallbacksAndMessages(mMediaToken);
+            mMediaHandler.removeCallbacksAndMessages(null);
             if (mMediaIsVisible && !nextVisible && mStatusBarState != StatusBarState.SHADE) {
                 // We need to delay this event for a few millis when stopping to avoid jank in the
                 // animation. The media app might not send its update when buffering, and the slice
                 // would end up without a header for 0.5 second.
                 mMediaWakeLock.setAcquired(true);
-                mHandler.postDelayed(() -> {
-                    updateMediaStateLocked(metadata, state);
-                    mMediaWakeLock.setAcquired(false);
-                }, mMediaToken, 2000);
+                mMediaHandler.postDelayed(() -> {
+                    synchronized (this) {
+                        updateMediaStateLocked(metadata, state);
+                        mMediaWakeLock.setAcquired(false);
+                    }
+                }, 2000);
             } else {
                 mMediaWakeLock.setAcquired(false);
                 updateMediaStateLocked(metadata, state);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e0270de..411bf9a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -68,6 +68,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
@@ -685,16 +686,22 @@
             Context context,
             FalsingManager falsingManager,
             LockPatternUtils lockPatternUtils) {
+        this(context, falsingManager, lockPatternUtils, SystemUIFactory.getInstance());
+    }
+
+    @VisibleForTesting
+    KeyguardViewMediator(
+            Context context,
+            FalsingManager falsingManager,
+            LockPatternUtils lockPatternUtils,
+            SystemUIFactory systemUIFactory) {
         super(context);
-
         mFalsingManager = falsingManager;
-
         mLockPatternUtils = lockPatternUtils;
-        mStatusBarKeyguardViewManager =
-                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(
-                        mContext,
-                        mViewMediatorCallback,
-                        mLockPatternUtils);
+        mStatusBarKeyguardViewManager = systemUIFactory.createStatusBarKeyguardViewManager(
+                mContext,
+                mViewMediatorCallback,
+                mLockPatternUtils);
     }
 
     public void userActivity() {
@@ -826,6 +833,11 @@
             mDeviceInteractive = false;
             mGoingToSleep = true;
 
+            // Reset keyguard going away state so we can start listening for fingerprint. We
+            // explicitly DO NOT want to call mStatusBarWindowController.setKeyguardGoingAway(false)
+            // here, since that will mess with the device lock state.
+            mUpdateMonitor.setKeyguardGoingAway(false);
+
             // Lock immediately based on setting if secure (user has a pin/pattern/password).
             // This also "locks" the device when not secure to provide easy access to the
             // camera while preventing unwanted input.
@@ -1572,12 +1584,14 @@
                     handleNotifyFinishedGoingToSleep();
                     break;
                 case NOTIFY_SCREEN_TURNING_ON:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNING_ON");
                     handleNotifyScreenTurningOn((IKeyguardDrawnCallback) msg.obj);
                     Trace.endSection();
                     break;
                 case NOTIFY_SCREEN_TURNED_ON:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_SCREEN_TURNED_ON");
                     handleNotifyScreenTurnedOn();
                     Trace.endSection();
                     break;
@@ -1585,7 +1599,8 @@
                     handleNotifyScreenTurnedOff();
                     break;
                 case NOTIFY_STARTED_WAKING_UP:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
                     handleNotifyStartedWakingUp();
                     Trace.endSection();
                     break;
@@ -1614,14 +1629,16 @@
                     handleDismiss(message.getCallback(), message.getMessage());
                     break;
                 case START_KEYGUARD_EXIT_ANIM:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
+                    Trace.beginSection(
+                            "KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
                     StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
                     handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
                     mFalsingManager.onSucccessfulUnlock();
                     Trace.endSection();
                     break;
                 case KEYGUARD_DONE_PENDING_TIMEOUT:
-                    Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE_PENDING_TIMEOUT");
+                    Trace.beginSection("KeyguardViewMediator#handleMessage"
+                            + " KEYGUARD_DONE_PENDING_TIMEOUT");
                     Log.w(TAG, "Timeout while waiting for activity drawn!");
                     Trace.endSection();
                     break;
@@ -1799,8 +1816,8 @@
             mHideAnimationRun = false;
             adjustStatusBarLocked();
             userActivity();
-            mUpdateMonitor.setKeyguardGoingAway(false /* away */);
-            mStatusBarWindowController.setKeyguardGoingAway(false /* goingAway */);
+            mUpdateMonitor.setKeyguardGoingAway(false);
+            mStatusBarWindowController.setKeyguardGoingAway(false);
             mShowKeyguardWakeLock.release();
         }
         mKeyguardDisplayManager.show();
@@ -1832,8 +1849,8 @@
                         .KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
             }
 
-            mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
-            mStatusBarWindowController.setKeyguardGoingAway(true /* goingAway */);
+            mUpdateMonitor.setKeyguardGoingAway(true);
+            mStatusBarWindowController.setKeyguardGoingAway(true);
 
             // Don't actually hide the Keyguard at the moment, wait for window
             // manager until it tells us it's safe to do so with
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index a9fe54b..4d061e1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -49,6 +49,12 @@
     private static final String TAG = "WorkLockActivity";
 
     /**
+     * Add additional extra {@link com.android.settings.password.ConfirmDeviceCredentialActivity} to
+     * enable device policy management enforcement from systemui.
+     */
+    public static final String EXTRA_FROM_WORK_LOCK_ACTIVITY = "from_work_lock_activity";
+
+    /**
      * Contains a {@link TaskDescription} for the activity being covered.
      */
     static final String EXTRA_TASK_DESCRIPTION =
@@ -151,6 +157,7 @@
 
         if (target != null) {
             credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
+            credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
         }
 
         startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 5723afd..c452f64 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -90,7 +90,7 @@
     public static final int MESSAGE_UPDATE_ACTIONS = 4;
     public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
     public static final int MESSAGE_ANIMATION_ENDED = 6;
-    public static final int MESSAGE_TOUCH_EVENT = 7;
+    public static final int MESSAGE_POINTER_EVENT = 7;
 
     private static final int INITIAL_DISMISS_DELAY = 3500;
     private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
@@ -165,9 +165,9 @@
                     break;
                 }
 
-                case MESSAGE_TOUCH_EVENT: {
+                case MESSAGE_POINTER_EVENT: {
                     final MotionEvent ev = (MotionEvent) msg.obj;
-                    dispatchTouchEvent(ev);
+                    dispatchPointerEvent(ev);
                     break;
                 }
             }
@@ -219,6 +219,9 @@
         updateFromIntent(getIntent());
         setTitle(R.string.pip_menu_title);
         setDisablePreviewScreenshots(true);
+
+        // Hide without an animation.
+        getWindow().setExitTransition(null);
     }
 
     @Override
@@ -269,6 +272,17 @@
         }
     }
 
+    /**
+     * Dispatch a pointer event from {@link PipTouchHandler}.
+     */
+    private void dispatchPointerEvent(MotionEvent event) {
+        if (event.isTouchEvent()) {
+            dispatchTouchEvent(event);
+        } else {
+            dispatchGenericMotionEvent(event);
+        }
+    }
+
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         if (!mAllowTouches) {
@@ -288,8 +302,6 @@
     public void finish() {
         notifyActivityCallback(null);
         super.finish();
-        // Hide without an animation (the menu should already be invisible at this point)
-        overridePendingTransition(0, 0);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 62c59e5..b8e0b81 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -508,12 +508,12 @@
     }
 
     /**
-     * Handles touch event sent from pip input consumer.
+     * Handles a pointer event sent from pip input consumer.
      */
-    void handleTouchEvent(MotionEvent ev) {
+    void handlePointerEvent(MotionEvent ev) {
         if (mToActivityMessenger != null) {
             Message m = Message.obtain();
-            m.what = PipMenuActivity.MESSAGE_TOUCH_EVENT;
+            m.what = PipMenuActivity.MESSAGE_POINTER_EVENT;
             m.obj = ev;
             try {
                 mToActivityMessenger.send(m);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 1f36d97..f59b372 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -132,6 +132,7 @@
     private boolean mSendingHoverAccessibilityEvents;
     private boolean mMovementWithinMinimize;
     private boolean mMovementWithinDismiss;
+    private PipAccessibilityInteractionConnection mConnection;
 
     // Touch state
     private final PipTouchState mTouchState;
@@ -213,9 +214,10 @@
         // Register the listener for input consumer touch events
         inputConsumerController.setInputListener(this::handleTouchEvent);
         inputConsumerController.setRegistrationListener(this::onRegistrationChanged);
-        onRegistrationChanged(inputConsumerController.isRegistered());
 
         mPipBoundsHandler = pipBoundsHandler;
+        mConnection = new PipAccessibilityInteractionConnection(mMotionHelper,
+                this::onAccessibilityShowMenu, mHandler);
     }
 
     public void setTouchEnabled(boolean enabled) {
@@ -339,9 +341,7 @@
 
     private void onRegistrationChanged(boolean isRegistered) {
         mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
-                ? new PipAccessibilityInteractionConnection(mMotionHelper,
-                        this::onAccessibilityShowMenu, mHandler) : null);
-
+                ? mConnection : null);
         if (!isRegistered && mTouchState.isUserInteracting()) {
             // If the input consumer is unregistered while the user is interacting, then we may not
             // get the final TOUCH_UP event, so clean up the dismiss target as well
@@ -409,27 +409,15 @@
             }
             case MotionEvent.ACTION_HOVER_ENTER:
             case MotionEvent.ACTION_HOVER_MOVE: {
-                if (mAccessibilityManager.isEnabled() && !mSendingHoverAccessibilityEvents) {
-                    AccessibilityEvent event = AccessibilityEvent.obtain(
-                            AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
-                    event.setImportantForAccessibility(true);
-                    event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
-                    event.setWindowId(
-                            AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
-                    mAccessibilityManager.sendAccessibilityEvent(event);
+                if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) {
+                    sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
                     mSendingHoverAccessibilityEvents = true;
                 }
                 break;
             }
             case MotionEvent.ACTION_HOVER_EXIT: {
-                if (mAccessibilityManager.isEnabled() && mSendingHoverAccessibilityEvents) {
-                    AccessibilityEvent event = AccessibilityEvent.obtain(
-                            AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
-                    event.setImportantForAccessibility(true);
-                    event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
-                    event.setWindowId(
-                            AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
-                    mAccessibilityManager.sendAccessibilityEvent(event);
+                if (!shouldDeliverToMenu && mSendingHoverAccessibilityEvents) {
+                    sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
                     mSendingHoverAccessibilityEvents = false;
                 }
                 break;
@@ -445,12 +433,25 @@
                 mMenuController.pokeMenu();
             }
 
-            mMenuController.handleTouchEvent(cloneEvent);
+            mMenuController.handlePointerEvent(cloneEvent);
         }
 
         return true;
     }
 
+    private void sendAccessibilityHoverEvent(int type) {
+        if (!mAccessibilityManager.isEnabled()) {
+            return;
+        }
+
+        AccessibilityEvent event = AccessibilityEvent.obtain(type);
+        event.setImportantForAccessibility(true);
+        event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
+        event.setWindowId(
+                AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
+        mAccessibilityManager.sendAccessibilityEvent(event);
+    }
+
     /**
      * Updates the appearance of the menu and scrim on top of the PiP while dismissing.
      */
@@ -523,6 +524,10 @@
      * Sets the menu visibility.
      */
     private void setMenuState(int menuState, boolean resize) {
+        if (mMenuState == menuState && !resize) {
+            return;
+        }
+
         if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
             // Save the current snap fraction and if we do not drag or move the PiP, then
             // we store back to this snap fraction.  Otherwise, we'll reset the snap
@@ -571,6 +576,9 @@
         }
         mMenuState = menuState;
         updateMovementBounds(menuState);
+        // If pip menu has dismissed, we should register the A11y ActionReplacingConnection for pip
+        // as well, or it can't handle a11y focus and pip menu can't perform any action.
+        onRegistrationChanged(menuState == MENU_STATE_NONE);
         if (menuState != MENU_STATE_CLOSE) {
             MetricsLoggerWrapper.logPictureInPictureMenuVisible(mContext, menuState == MENU_STATE_FULL);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 98f0b2a..f60d9db 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -55,7 +55,11 @@
 import java.util.concurrent.Future;
 
 import javax.inject.Inject;
+import javax.inject.Singleton;
 
+import dagger.Lazy;
+
+@Singleton
 public class PowerUI extends SystemUI {
 
     static final String TAG = "PowerUI";
@@ -101,11 +105,14 @@
     private IThermalEventListener mSkinThermalEventListener;
     private IThermalEventListener mUsbThermalEventListener;
     private final BroadcastDispatcher mBroadcastDispatcher;
+    private final Lazy<StatusBar> mStatusBarLazy;
 
     @Inject
-    public PowerUI(Context context, BroadcastDispatcher broadcastDispatcher) {
+    public PowerUI(Context context, BroadcastDispatcher broadcastDispatcher,
+            Lazy<StatusBar> statusBarLazy) {
         super(context);
         mBroadcastDispatcher = broadcastDispatcher;
+        mStatusBarLazy = statusBarLazy;
     }
 
     public void start() {
@@ -663,8 +670,7 @@
             int status = temp.getStatus();
 
             if (status >= Temperature.THROTTLING_EMERGENCY) {
-                StatusBar statusBar = getComponent(StatusBar.class);
-                if (statusBar != null && !statusBar.isDeviceInVrMode()) {
+                if (!mStatusBarLazy.get().isDeviceInVrMode()) {
                     mWarnings.showHighTemperatureWarning();
                     Slog.d(TAG, "SkinThermalEventListener: notifyThrottling was called "
                             + ", current skin status = " + status
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 631b8b7..22fb4c0 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -22,25 +22,20 @@
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
-import android.os.Handler
-import android.os.Looper
-import android.os.Message
-import android.os.UserHandle
-import android.os.UserManager
+import android.os.*
 import android.provider.DeviceConfig
 import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
-import com.android.systemui.Dependency.BG_HANDLER_NAME
-import com.android.systemui.Dependency.MAIN_HANDLER_NAME
+import com.android.systemui.Dumpable
 import com.android.systemui.R
 import com.android.systemui.appops.AppOpItem
 import com.android.systemui.appops.AppOpsController
-import com.android.systemui.Dumpable
+import com.android.systemui.dagger.qualifiers.BgHandler
+import com.android.systemui.dagger.qualifiers.MainHandler
 import java.io.FileDescriptor
 import java.io.PrintWriter
 import java.lang.ref.WeakReference
 import javax.inject.Inject
-import javax.inject.Named
 import javax.inject.Singleton
 
 fun isPermissionsHubEnabled() = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
@@ -50,8 +45,8 @@
 class PrivacyItemController @Inject constructor(
     val context: Context,
     private val appOpsController: AppOpsController,
-    @Named(MAIN_HANDLER_NAME) private val uiHandler: Handler,
-    @Named(BG_HANDLER_NAME) private val bgHandler: Handler
+    @MainHandler private val uiHandler: Handler,
+    @BgHandler private val bgHandler: Handler
 ) : Dumpable {
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
new file mode 100644
index 0000000..f710f7f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
@@ -0,0 +1,133 @@
+/*
+ * 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.systemui.qs
+
+import android.content.Context
+import android.content.res.Configuration
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
+import com.android.systemui.qs.TileLayout.exactly
+
+class DoubleLineTileLayout(context: Context) : ViewGroup(context), QSPanel.QSTileLayout {
+
+    protected val mRecords = ArrayList<QSPanel.TileRecord>()
+    private var _listening = false
+    private var smallTileSize = 0
+    private val twoLineHeight
+        get() = smallTileSize * 2 + cellMarginVertical
+    private var cellMarginHorizontal = 0
+    private var cellMarginVertical = 0
+
+    init {
+        isFocusableInTouchMode = true
+        clipChildren = false
+        clipToPadding = false
+
+        updateResources()
+    }
+
+    override fun addTile(tile: QSPanel.TileRecord) {
+        mRecords.add(tile)
+        tile.tile.setListening(this, _listening)
+        addTileView(tile)
+    }
+
+    protected fun addTileView(tile: QSPanel.TileRecord) {
+        addView(tile.tileView)
+    }
+
+    override fun removeTile(tile: QSPanel.TileRecord) {
+        mRecords.remove(tile)
+        tile.tile.setListening(this, false)
+        removeView(tile.tileView)
+    }
+
+    override fun removeAllViews() {
+        mRecords.forEach { it.tile.setListening(this, false) }
+        mRecords.clear()
+        super.removeAllViews()
+    }
+
+    override fun getOffsetTop(tile: QSPanel.TileRecord?) = top
+
+    override fun updateResources(): Boolean {
+        with(mContext.resources) {
+            smallTileSize = getDimensionPixelSize(R.dimen.qs_quick_tile_size)
+            cellMarginHorizontal = getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal)
+            cellMarginVertical = getDimensionPixelSize(R.dimen.new_qs_vertical_margin)
+        }
+        requestLayout()
+        return false
+    }
+
+    override fun setListening(listening: Boolean) {
+        if (_listening == listening) return
+        _listening = listening
+        for (record in mRecords) {
+            record.tile.setListening(this, listening)
+        }
+    }
+
+    override fun getNumVisibleTiles() = mRecords.size
+
+    override fun onConfigurationChanged(newConfig: Configuration) {
+        super.onConfigurationChanged(newConfig)
+        updateResources()
+    }
+
+    override fun onFinishInflate() {
+        updateResources()
+    }
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        var previousView: View = this
+        var tiles = 0
+
+        mRecords.forEach {
+            val tileView = it.tileView
+            if (tileView.visibility != View.GONE) {
+                tileView.updateAccessibilityOrder(previousView)
+                previousView = tileView
+                tiles++
+                tileView.measure(exactly(smallTileSize), exactly(smallTileSize))
+            }
+        }
+
+        val height = twoLineHeight
+        val columns = tiles / 2
+        val width = paddingStart + paddingEnd +
+                columns * smallTileSize +
+                (columns - 1) * cellMarginHorizontal
+        setMeasuredDimension(width, height)
+    }
+
+    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
+        val tiles = mRecords.filter { it.tileView.visibility != View.GONE }
+        tiles.forEachIndexed {
+            index, tile ->
+            val column = index % (tiles.size / 2)
+            val left = getLeftForColumn(column)
+            val top = if (index < tiles.size / 2) 0 else getTopBottomRow()
+            tile.tileView.layout(left, top, left + smallTileSize, top + smallTileSize)
+        }
+    }
+
+    private fun getLeftForColumn(column: Int) = column * (smallTileSize + cellMarginHorizontal)
+
+    private fun getTopBottomRow() = smallTileSize + cellMarginVertical
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 9221b68..a267bbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -14,6 +14,7 @@
 
 package com.android.systemui.qs;
 
+import android.provider.Settings;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
@@ -267,6 +268,17 @@
             mAllViews.add(tileView);
             count++;
         }
+
+
+        int flag = Settings.System.getInt(mQsPanel.getContext().getContentResolver(),
+                "qs_media_player", 0);
+        if (flag == 1) {
+            View qsMediaView = mQsPanel.getMediaPanel();
+            View qqsMediaView = mQuickQsPanel.getMediaPlayer().getView();
+            translationXBuilder.addFloat(qsMediaView, "alpha", 0, 1);
+            translationXBuilder.addFloat(qqsMediaView, "alpha", 1, 0);
+        }
+
         if (mAllowFancy) {
             // Make brightness appear static position and alpha in through second half.
             View brightness = mQsPanel.getBrightnessView();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
index b9f3a7f..5742787 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
@@ -17,9 +17,7 @@
 package com.android.systemui.qs;
 
 import static com.android.systemui.Dependency.BG_HANDLER;
-import static com.android.systemui.Dependency.BG_HANDLER_NAME;
 import static com.android.systemui.Dependency.MAIN_LOOPER;
-import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
 import android.annotation.MainThread;
@@ -41,6 +39,8 @@
 import com.android.keyguard.CarrierTextController;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainLooper;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.policy.NetworkController;
 
@@ -77,8 +77,8 @@
     @Inject
     public QSCarrierGroup(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
             NetworkController networkController, ActivityStarter activityStarter,
-            @Named(BG_HANDLER_NAME) Handler handler,
-            @Named(MAIN_LOOPER_NAME) Looper looper) {
+            @BgHandler Handler handler,
+            @MainLooper Looper looper) {
         super(context, attrs);
         mNetworkController = networkController;
         mActivityStarter = activityStarter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
new file mode 100644
index 0000000..6949640
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
@@ -0,0 +1,306 @@
+/*
+ * 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.systemui.qs;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.Icon;
+import android.graphics.drawable.RippleDrawable;
+import android.media.MediaMetadata;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
+import com.android.settingslib.media.MediaOutputSliceConstants;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+
+/**
+ * Single media player for carousel in QSPanel
+ */
+public class QSMediaPlayer {
+
+    private static final String TAG = "QSMediaPlayer";
+
+    private Context mContext;
+    private LinearLayout mMediaNotifView;
+    private MediaSession.Token mToken;
+    private MediaController mController;
+    private int mWidth;
+    private int mHeight;
+
+    /**
+     *
+     * @param context
+     * @param parent
+     * @param width
+     * @param height
+     */
+    public QSMediaPlayer(Context context, ViewGroup parent, int width, int height) {
+        mContext = context;
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        mMediaNotifView = (LinearLayout) inflater.inflate(R.layout.qs_media_panel, parent, false);
+
+        mWidth = width;
+        mHeight = height;
+    }
+
+    public View getView() {
+        return mMediaNotifView;
+    }
+
+    /**
+     *
+     * @param token token for this media session
+     * @param icon app notification icon
+     * @param iconColor foreground color (for text, icons)
+     * @param bgColor background color
+     * @param actionsContainer a LinearLayout containing the media action buttons
+     * @param notif
+     */
+    public void setMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
+            View actionsContainer, Notification notif) {
+        Log.d(TAG, "got media session: " + token);
+        mToken = token;
+        mController = new MediaController(mContext, token);
+        MediaMetadata mMediaMetadata = mController.getMetadata();
+
+        if (mMediaMetadata == null) {
+            Log.e(TAG, "Media metadata was null");
+            return;
+        }
+
+        Notification.Builder builder = Notification.Builder.recoverBuilder(mContext, notif);
+
+        // Album art
+        addAlbumArtBackground(mMediaMetadata, bgColor, mWidth, mHeight);
+
+        // Reuse notification header instead of reimplementing everything
+        RemoteViews headerRemoteView = builder.makeNotificationHeader();
+        LinearLayout headerView = mMediaNotifView.findViewById(R.id.header);
+        View result = headerRemoteView.apply(mContext, headerView);
+        result.setPadding(0, 0, 0, 0);
+        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, 75);
+        result.setLayoutParams(lp);
+        headerView.removeAllViews();
+        headerView.addView(result);
+
+        View seamless = headerView.findViewById(com.android.internal.R.id.media_seamless);
+        seamless.setVisibility(View.VISIBLE);
+
+        // App icon
+        ImageView appIcon = headerView.findViewById(com.android.internal.R.id.icon);
+        Drawable iconDrawable = icon.loadDrawable(mContext);
+        iconDrawable.setTint(iconColor);
+        appIcon.setImageDrawable(iconDrawable);
+
+        // App title
+        TextView appName = headerView.findViewById(com.android.internal.R.id.app_name_text);
+        String appNameString = builder.loadHeaderAppName();
+        appName.setText(appNameString);
+        appName.setTextColor(iconColor);
+
+        // Action
+        mMediaNotifView.setOnClickListener(v -> {
+            try {
+                notif.contentIntent.send();
+                // Also close shade
+                mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+            } catch (PendingIntent.CanceledException e) {
+                Log.e(TAG, "Pending intent was canceled");
+                e.printStackTrace();
+            }
+        });
+
+        // Separator
+        TextView separator = headerView.findViewById(com.android.internal.R.id.header_text_divider);
+        separator.setTextColor(iconColor);
+
+        // Album name
+        TextView albumName = headerView.findViewById(com.android.internal.R.id.header_text);
+        String albumString = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ALBUM);
+        if (TextUtils.isEmpty(albumString)) {
+            albumName.setVisibility(View.GONE);
+            separator.setVisibility(View.GONE);
+        } else {
+            albumName.setText(albumString);
+            albumName.setTextColor(iconColor);
+            albumName.setVisibility(View.VISIBLE);
+            separator.setVisibility(View.VISIBLE);
+        }
+
+        // Transfer chip
+        View transferBackgroundView = headerView.findViewById(
+                com.android.internal.R.id.media_seamless);
+        LinearLayout viewLayout = (LinearLayout) transferBackgroundView;
+        RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground();
+        GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
+        rect.setStroke(2, iconColor);
+        rect.setColor(bgColor);
+        ImageView transferIcon = headerView.findViewById(
+                com.android.internal.R.id.media_seamless_image);
+        transferIcon.setBackgroundColor(bgColor);
+        transferIcon.setImageTintList(ColorStateList.valueOf(iconColor));
+        TextView transferText = headerView.findViewById(
+                com.android.internal.R.id.media_seamless_text);
+        transferText.setTextColor(iconColor);
+
+        ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
+        transferBackgroundView.setOnClickListener(v -> {
+            final Intent intent = new Intent()
+                    .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT);
+            mActivityStarter.startActivity(intent, false, true /* dismissShade */,
+                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        });
+
+        // Artist name
+        TextView artistText = mMediaNotifView.findViewById(R.id.header_title);
+        String artistName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
+        artistText.setText(artistName);
+        artistText.setTextColor(iconColor);
+
+        // Song name
+        TextView titleText = mMediaNotifView.findViewById(R.id.header_text);
+        String songName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
+        titleText.setText(songName);
+        titleText.setTextColor(iconColor);
+
+        // Media controls
+        LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
+        final int[] actionIds = {
+                R.id.action0,
+                R.id.action1,
+                R.id.action2,
+                R.id.action3,
+                R.id.action4
+        };
+        final int[] notifActionIds = {
+                com.android.internal.R.id.action0,
+                com.android.internal.R.id.action1,
+                com.android.internal.R.id.action2,
+                com.android.internal.R.id.action3,
+                com.android.internal.R.id.action4
+        };
+        for (int i = 0; i < parentActionsLayout.getChildCount() && i < actionIds.length; i++) {
+            ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]);
+            ImageButton thatBtn = parentActionsLayout.findViewById(notifActionIds[i]);
+            if (thatBtn == null || thatBtn.getDrawable() == null) {
+                thisBtn.setVisibility(View.GONE);
+                continue;
+            }
+
+            Drawable thatIcon = thatBtn.getDrawable();
+            thisBtn.setImageDrawable(thatIcon.mutate());
+            thisBtn.setVisibility(View.VISIBLE);
+            thisBtn.setOnClickListener(v -> {
+                Log.d(TAG, "clicking on other button");
+                thatBtn.performClick();
+            });
+        }
+    }
+
+    public MediaSession.Token getMediaSessionToken() {
+        return mToken;
+    }
+
+    public String getMediaPlayerPackage() {
+        return mController.getPackageName();
+    }
+
+    /**
+     * Check whether the media controlled by this player is currently playing
+     * @return whether it is playing, or false if no controller information
+     */
+    public boolean isPlaying() {
+        if (mController == null) {
+            return false;
+        }
+
+        PlaybackState state = mController.getPlaybackState();
+        if (state == null) {
+            return false;
+        }
+
+        return (state.getState() == PlaybackState.STATE_PLAYING);
+    }
+
+    private void addAlbumArtBackground(MediaMetadata metadata, int bgColor, int width, int height) {
+        Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+        if (albumArt != null) {
+
+            Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true);
+            Bitmap scaled = scaleBitmap(original, width, height);
+            Canvas canvas = new Canvas(scaled);
+
+            // Add translucent layer over album art to improve contrast
+            Paint p = new Paint();
+            p.setStyle(Paint.Style.FILL);
+            p.setColor(bgColor);
+            p.setAlpha(200);
+            canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), p);
+
+            RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
+                    mContext.getResources(), scaled);
+            roundedDrawable.setCornerRadius(20);
+
+            mMediaNotifView.setBackground(roundedDrawable);
+        } else {
+            Log.e(TAG, "No album art available");
+        }
+    }
+
+    private Bitmap scaleBitmap(Bitmap original, int width, int height) {
+        Bitmap cropped = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(cropped);
+
+        float scale = (float) cropped.getWidth() / (float) original.getWidth();
+        float dy = (cropped.getHeight() - original.getHeight() * scale) / 2.0f;
+        Matrix transformation = new Matrix();
+        transformation.postTranslate(0, dy);
+        transformation.preScale(scale, scale);
+
+        Paint paint = new Paint();
+        paint.setFilterBitmap(true);
+        canvas.drawBitmap(original, transformation, paint);
+
+        return cropped;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 2e24403..b48814b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -24,16 +24,22 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.drawable.Icon;
+import android.media.session.MediaSession;
 import android.metrics.LogMaker;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
 import android.service.quicksettings.Tile;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
 import android.widget.LinearLayout;
 
 import com.android.internal.logging.MetricsLogger;
@@ -82,6 +88,9 @@
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
     private final QSTileRevealController mQsTileRevealController;
 
+    private final LinearLayout mMediaCarousel;
+    private final ArrayList<QSMediaPlayer> mMediaPlayers = new ArrayList<>();
+
     protected boolean mExpanded;
     protected boolean mListening;
 
@@ -140,6 +149,28 @@
 
         addDivider();
 
+        // Add media carousel
+        int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0);
+        if (flag == 1) {
+            HorizontalScrollView mediaScrollView = new HorizontalScrollView(mContext);
+            mediaScrollView.setHorizontalScrollBarEnabled(false);
+            int playerHeight = (int) getResources().getDimension(R.dimen.qs_media_height);
+            int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
+            LayoutParams lpView = new LayoutParams(LayoutParams.MATCH_PARENT, playerHeight);
+            lpView.setMarginStart(padding);
+            lpView.setMarginEnd(padding);
+            addView(mediaScrollView, lpView);
+
+            LayoutParams lpCarousel = new LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.WRAP_CONTENT);
+            mMediaCarousel = new LinearLayout(mContext);
+            mMediaCarousel.setOrientation(LinearLayout.HORIZONTAL);
+            mediaScrollView.addView(mMediaCarousel, lpCarousel);
+            mediaScrollView.setVisibility(View.GONE);
+        } else {
+            mMediaCarousel = null;
+        }
+
         mFooter = new QSSecurityFooter(this, context);
         addView(mFooter.getView());
 
@@ -159,6 +190,76 @@
 
     }
 
+    /**
+     * Add or update a player for the associated media session
+     * @param token
+     * @param icon
+     * @param iconColor
+     * @param bgColor
+     * @param actionsContainer
+     * @param notif
+     */
+    public void addMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
+            View actionsContainer, StatusBarNotification notif) {
+        int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
+        if (flag != 1) {
+            // Shouldn't happen, but just in case
+            Log.e(TAG, "Tried to add media session without player!");
+            return;
+        }
+        QSMediaPlayer player = null;
+        String packageName = notif.getPackageName();
+        for (QSMediaPlayer p : mMediaPlayers) {
+            if (p.getMediaSessionToken().equals(token)) {
+                Log.d(TAG, "a player for this session already exists");
+                player = p;
+                break;
+            }
+
+            if (packageName.equals(p.getMediaPlayerPackage())) {
+                Log.d(TAG, "found an old session for this app");
+                player = p;
+                break;
+            }
+        }
+
+        int playerHeight = (int) getResources().getDimension(R.dimen.qs_media_height);
+        int playerWidth = (int) getResources().getDimension(R.dimen.qs_media_width);
+        int padding = (int) getResources().getDimension(R.dimen.qs_media_padding);
+        LayoutParams lp = new LayoutParams(playerWidth, ViewGroup.LayoutParams.MATCH_PARENT);
+        lp.setMarginStart(padding);
+        lp.setMarginEnd(padding);
+
+        if (player == null) {
+            Log.d(TAG, "creating new player");
+
+            player = new QSMediaPlayer(mContext, this, playerWidth, playerHeight);
+
+            if (player.isPlaying()) {
+                mMediaCarousel.addView(player.getView(), 0, lp); // add in front
+            } else {
+                mMediaCarousel.addView(player.getView(), lp); // add at end
+            }
+            mMediaPlayers.add(player);
+        } else if (player.isPlaying()) {
+            // move it to the front
+            mMediaCarousel.removeView(player.getView());
+            mMediaCarousel.addView(player.getView(), 0, lp);
+        }
+
+        Log.d(TAG, "setting player session");
+        player.setMediaSession(token, icon, iconColor, bgColor, actionsContainer,
+                notif.getNotification());
+
+        if (mMediaPlayers.size() > 0) {
+            ((View) mMediaCarousel.getParent()).setVisibility(View.VISIBLE);
+        }
+    }
+
+    protected View getMediaPanel() {
+        return mMediaCarousel;
+    }
+
     protected void addDivider() {
         mDivider = LayoutInflater.from(mContext).inflate(R.layout.qs_divider, this, false);
         mDivider.setBackgroundColor(Utils.applyAlpha(mDivider.getAlpha(),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 1e763cf..b395c3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -30,11 +30,12 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.DumpController;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.qs.QSFactory;
 import com.android.systemui.plugins.qs.QSTile;
@@ -61,7 +62,6 @@
 import java.util.function.Predicate;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Provider;
 import javax.inject.Singleton;
 
@@ -94,8 +94,8 @@
     public QSTileHost(Context context,
             StatusBarIconController iconController,
             QSFactoryImpl defaultFactory,
-            @Named(Dependency.MAIN_HANDLER_NAME) Handler mainHandler,
-            @Named(Dependency.BG_LOOPER_NAME) Looper bgLooper,
+            @MainHandler Handler mainHandler,
+            @BgLooper Looper bgLooper,
             PluginManager pluginManager,
             TunerService tunerService,
             Provider<AutoTileManager> autoTiles,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
new file mode 100644
index 0000000..3ec71ac
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
@@ -0,0 +1,208 @@
+/*
+ * 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.systemui.qs;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.media.MediaMetadata;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
+import com.android.systemui.R;
+
+/**
+ * QQS mini media player
+ */
+public class QuickQSMediaPlayer {
+
+    private static final String TAG = "QQSMediaPlayer";
+
+    private Context mContext;
+    private LinearLayout mMediaNotifView;
+    private MediaSession.Token mToken;
+    private MediaController mController;
+
+    /**
+     *
+     * @param context
+     * @param parent
+     */
+    public QuickQSMediaPlayer(Context context, ViewGroup parent) {
+        mContext = context;
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        mMediaNotifView = (LinearLayout) inflater.inflate(R.layout.qqs_media_panel, parent, false);
+    }
+
+    public View getView() {
+        return mMediaNotifView;
+    }
+
+    /**
+     *
+     * @param token token for this media session
+     * @param icon app notification icon
+     * @param iconColor foreground color (for text, icons)
+     * @param bgColor background color
+     * @param actionsContainer a LinearLayout containing the media action buttons
+     */
+    public void setMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
+            View actionsContainer) {
+        Log.d(TAG, "Setting media session: " + token);
+        mToken = token;
+        mController = new MediaController(mContext, token);
+        MediaMetadata mMediaMetadata = mController.getMetadata();
+
+        if (mMediaMetadata == null) {
+            Log.e(TAG, "Media metadata was null");
+            return;
+        }
+
+        // Album art
+        addAlbumArtBackground(mMediaMetadata, bgColor);
+
+        // App icon
+        ImageView appIcon = mMediaNotifView.findViewById(R.id.icon);
+        Drawable iconDrawable = icon.loadDrawable(mContext);
+        iconDrawable.setTint(iconColor);
+        appIcon.setImageDrawable(iconDrawable);
+
+        // Artist name
+        TextView appText = mMediaNotifView.findViewById(R.id.header_title);
+        String artistName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
+        appText.setText(artistName);
+        appText.setTextColor(iconColor);
+
+        // Song name
+        TextView titleText = mMediaNotifView.findViewById(R.id.header_text);
+        String songName = mMediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
+        titleText.setText(songName);
+        titleText.setTextColor(iconColor);
+
+        // Action buttons
+        LinearLayout parentActionsLayout = (LinearLayout) actionsContainer;
+        final int[] actionIds = {R.id.action0, R.id.action1, R.id.action2};
+
+        // TODO some apps choose different buttons to show in compact mode
+        final int[] notifActionIds = {
+                com.android.internal.R.id.action1,
+                com.android.internal.R.id.action2,
+                com.android.internal.R.id.action3
+        };
+        for (int i = 0; i < parentActionsLayout.getChildCount() && i < actionIds.length; i++) {
+            ImageButton thisBtn = mMediaNotifView.findViewById(actionIds[i]);
+            ImageButton thatBtn = parentActionsLayout.findViewById(notifActionIds[i]);
+            if (thatBtn == null || thatBtn.getDrawable() == null) {
+                thisBtn.setVisibility(View.GONE);
+                continue;
+            }
+
+            Drawable thatIcon = thatBtn.getDrawable();
+            thisBtn.setImageDrawable(thatIcon.mutate());
+            thisBtn.setVisibility(View.VISIBLE);
+
+            thisBtn.setOnClickListener(v -> {
+                Log.d(TAG, "clicking on other button");
+                thatBtn.performClick();
+            });
+        }
+    }
+
+    public MediaSession.Token getMediaSessionToken() {
+        return mToken;
+    }
+
+    /**
+     * Check whether the media controlled by this player is currently playing
+     * @return whether it is playing, or false if no controller information
+     */
+    public boolean isPlaying() {
+        if (mController == null) {
+            return false;
+        }
+
+        PlaybackState state = mController.getPlaybackState();
+        if (state == null) {
+            return false;
+        }
+
+        return (state.getState() == PlaybackState.STATE_PLAYING);
+    }
+
+    private void addAlbumArtBackground(MediaMetadata metadata, int bgColor) {
+        Bitmap albumArt = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+        if (albumArt != null) {
+            Rect bounds = new Rect();
+            mMediaNotifView.getBoundsOnScreen(bounds);
+            int width = bounds.width();
+            int height = bounds.height();
+
+            Bitmap original = albumArt.copy(Bitmap.Config.ARGB_8888, true);
+            Bitmap scaled = scaleBitmap(original, width, height);
+            Canvas canvas = new Canvas(scaled);
+
+            // Add translucent layer over album art to improve contrast
+            Paint p = new Paint();
+            p.setStyle(Paint.Style.FILL);
+            p.setColor(bgColor);
+            p.setAlpha(200);
+            canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), p);
+
+            RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
+                    mContext.getResources(), scaled);
+            roundedDrawable.setCornerRadius(20);
+
+            mMediaNotifView.setBackground(roundedDrawable);
+        } else {
+            Log.e(TAG, "No album art available");
+        }
+    }
+
+    private Bitmap scaleBitmap(Bitmap original, int width, int height) {
+        Bitmap cropped = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(cropped);
+
+        float scale = (float) cropped.getWidth() / (float) original.getWidth();
+        float dy = (cropped.getHeight() - original.getHeight() * scale) / 2.0f;
+        Matrix transformation = new Matrix();
+        transformation.postTranslate(0, dy);
+        transformation.preScale(scale, scale);
+
+        Paint paint = new Paint();
+        paint.setFilterBitmap(true);
+        canvas.drawBitmap(original, transformation, paint);
+
+        return cropped;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 85aafa0..dcd4633 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
@@ -55,6 +56,7 @@
     private boolean mDisabledByPolicy;
     private int mMaxTiles;
     protected QSPanel mFullPanel;
+    private QuickQSMediaPlayer mMediaPlayer;
 
     @Inject
     public QuickQSPanel(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
@@ -69,11 +71,43 @@
             }
             removeView((View) mTileLayout);
         }
-        sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
-        mTileLayout = new HeaderTileLayout(context);
-        mTileLayout.setListening(mListening);
-        addView((View) mTileLayout, 0 /* Between brightness and footer */);
-        super.setPadding(0, 0, 0, 0);
+
+        int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0);
+        if (flag == 1) {
+            LinearLayout mHorizontalLinearLayout = new LinearLayout(mContext);
+            mHorizontalLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
+            mHorizontalLinearLayout.setClipChildren(false);
+            mHorizontalLinearLayout.setClipToPadding(false);
+
+            LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
+
+            mTileLayout = new DoubleLineTileLayout(context);
+            lp.setMarginEnd(10);
+            lp.setMarginStart(0);
+            mHorizontalLinearLayout.addView((View) mTileLayout, lp);
+
+            mMediaPlayer = new QuickQSMediaPlayer(mContext, mHorizontalLinearLayout);
+
+            lp.setMarginEnd(0);
+            lp.setMarginStart(10);
+            mHorizontalLinearLayout.addView(mMediaPlayer.getView(), lp);
+
+            sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
+
+            mTileLayout.setListening(mListening);
+            addView(mHorizontalLinearLayout, 0 /* Between brightness and footer */);
+            super.setPadding(0, 0, 0, 0);
+        } else {
+            sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
+            mTileLayout = new HeaderTileLayout(context);
+            mTileLayout.setListening(mListening);
+            addView((View) mTileLayout, 0 /* Between brightness and footer */);
+            super.setPadding(0, 0, 0, 0);
+        }
+    }
+
+    public QuickQSMediaPlayer getMediaPlayer() {
+        return mMediaPlayer;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 4013586..592e388 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -392,9 +392,15 @@
         mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
 
         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+
+        int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
         if (mQsDisabled) {
             lp.height = resources.getDimensionPixelSize(
                     com.android.internal.R.dimen.quick_qs_offset_height);
+        } else if (flag == 1) {
+            lp.height = Math.max(getMinimumHeight(),
+                    resources.getDimensionPixelSize(
+                            com.android.internal.R.dimen.quick_qs_total_height_with_media));
         } else {
             lp.height = Math.max(getMinimumHeight(),
                     resources.getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 1c8e451..9a33c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -145,7 +145,7 @@
                 return mBluetoothTileProvider.get();
             case "controls":
                 if (Settings.System.getInt(mHost.getContext().getContentResolver(),
-                        "qs_controls_tile_enabled", 0) == 1) {
+                        "npv_plugin_flag", 0) == 3) {
                     return mControlsTileProvider.get();
                 } else return null;
             case "cell":
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java
index 0a59618..39ae66e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java
@@ -22,11 +22,11 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.LinearLayout;
+import android.widget.FrameLayout;
 
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.HomeControlsPlugin;
+import com.android.systemui.plugins.NPVPlugin;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -44,7 +44,7 @@
     private ControlsDetailAdapter mDetailAdapter;
     private final ActivityStarter mActivityStarter;
     private PluginManager mPluginManager;
-    private HomeControlsPlugin mPlugin;
+    private NPVPlugin mPlugin;
     private Intent mHomeAppIntent;
 
     @Inject
@@ -81,7 +81,7 @@
     public void setDetailListening(boolean listening) {
         if (mPlugin == null) return;
 
-        mPlugin.setVisible(listening);
+        mPlugin.setListening(listening);
     }
 
     @Override
@@ -142,7 +142,7 @@
 
     private class ControlsDetailAdapter implements DetailAdapter {
         private View mDetailView;
-        protected LinearLayout mHomeControlsLayout;
+        protected FrameLayout mHomeControlsLayout;
 
         public CharSequence getTitle() {
             return "Controls";
@@ -157,24 +157,30 @@
         }
 
         public View createDetailView(Context context, View convertView, final ViewGroup parent) {
-            mHomeControlsLayout = (LinearLayout) LayoutInflater.from(context).inflate(
-                R.layout.home_controls, parent, false);
+            if (convertView != null) return convertView;
+
+            mHomeControlsLayout = (FrameLayout) LayoutInflater.from(context).inflate(
+                    R.layout.home_controls, parent, false);
             mHomeControlsLayout.setVisibility(View.VISIBLE);
+            parent.addView(mHomeControlsLayout);
+
             mPluginManager.addPluginListener(
-                    new PluginListener<HomeControlsPlugin>() {
+                    new PluginListener<NPVPlugin>() {
                         @Override
-                        public void onPluginConnected(HomeControlsPlugin plugin,
+                        public void onPluginConnected(NPVPlugin plugin,
                                                       Context pluginContext) {
                             mPlugin = plugin;
-                            mPlugin.sendParentGroup(mHomeControlsLayout);
-                            mPlugin.setVisible(true);
+                            mPlugin.attachToRoot(mHomeControlsLayout);
+                            mPlugin.setListening(true);
                         }
 
                         @Override
-                        public void onPluginDisconnected(HomeControlsPlugin plugin) {
+                        public void onPluginDisconnected(NPVPlugin plugin) {
+                            mPlugin.setListening(false);
+                            mHomeControlsLayout.removeAllViews();
 
                         }
-                    }, HomeControlsPlugin.class, false);
+                    }, NPVPlugin.class, false);
             return mHomeControlsLayout;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 33bcefb..e24a362 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -65,7 +65,7 @@
             Log.v(TAG, "showNotification");
         }
         addAlertEntry(entry);
-        updateNotification(entry.key, true /* alert */);
+        updateNotification(entry.getKey(), true /* alert */);
         entry.setInterruption();
     }
 
@@ -182,7 +182,7 @@
     protected final void addAlertEntry(@NonNull NotificationEntry entry) {
         AlertEntry alertEntry = createAlertEntry();
         alertEntry.setEntry(entry);
-        mAlertEntries.put(entry.key, alertEntry);
+        mAlertEntries.put(entry.getKey(), alertEntry);
         onAlertEntryAdded(alertEntry);
         entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
     }
@@ -251,7 +251,7 @@
 
     @Override
     public boolean shouldExtendLifetime(NotificationEntry entry) {
-        return !canRemoveImmediately(entry.key);
+        return !canRemoveImmediately(entry.getKey());
     }
 
     @Override
@@ -260,7 +260,7 @@
             mExtendedLifetimeAlertEntries.add(entry);
             // We need to make sure that entries are stopping to alert eventually, let's remove
             // this as soon as possible.
-            AlertEntry alertEntry = mAlertEntries.get(entry.key);
+            AlertEntry alertEntry = mAlertEntries.get(entry.getKey());
             alertEntry.removeAsSoonAsPossible();
         } else {
             mExtendedLifetimeAlertEntries.remove(entry);
@@ -276,7 +276,7 @@
         @Nullable protected Runnable mRemoveAlertRunnable;
 
         public void setEntry(@NonNull final NotificationEntry entry) {
-            setEntry(entry, () -> removeAlertEntry(entry.key));
+            setEntry(entry, () -> removeAlertEntry(entry.getKey()));
         }
 
         public void setEntry(@NonNull final NotificationEntry entry,
@@ -332,7 +332,7 @@
         public int compareTo(@NonNull AlertEntry alertEntry) {
             return (mPostTime < alertEntry.mPostTime)
                     ? 1 : ((mPostTime == alertEntry.mPostTime)
-                            ? mEntry.key.compareTo(alertEntry.mEntry.key) : -1);
+                            ? mEntry.getKey().compareTo(alertEntry.mEntry.getKey()) : -1);
         }
 
         public void reset() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index d6a8f90..34f5437 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -22,6 +22,8 @@
 import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
 
 import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
 
@@ -43,12 +45,17 @@
 import android.os.Message;
 import android.util.Pair;
 import android.util.SparseArray;
+import android.view.InsetsFlags;
+import android.view.InsetsState.InternalInsetType;
+import android.view.View;
+import android.view.WindowInsetsController.Appearance;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.policy.CallbackController;
@@ -76,7 +83,7 @@
     private static final int MSG_EXPAND_NOTIFICATIONS          = 3 << MSG_SHIFT;
     private static final int MSG_COLLAPSE_PANELS               = 4 << MSG_SHIFT;
     private static final int MSG_EXPAND_SETTINGS               = 5 << MSG_SHIFT;
-    private static final int MSG_SET_SYSTEMUI_VISIBILITY       = 6 << MSG_SHIFT;
+    private static final int MSG_SYSTEM_BAR_APPEARANCE_CHANGED = 6 << MSG_SHIFT;
     private static final int MSG_DISPLAY_READY                 = 7 << MSG_SHIFT;
     private static final int MSG_SHOW_IME_BUTTON               = 8 << MSG_SHIFT;
     private static final int MSG_TOGGLE_RECENT_APPS            = 9 << MSG_SHIFT;
@@ -115,6 +122,9 @@
     private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
     private static final int MSG_SHOW_PINNING_TOAST_ESCAPE     = 46 << MSG_SHIFT;
     private static final int MSG_RECENTS_ANIMATION_STATE_CHANGED = 47 << MSG_SHIFT;
+    private static final int MSG_SHOW_TRANSIENT                = 48 << MSG_SHIFT;
+    private static final int MSG_ABORT_TRANSIENT               = 49 << MSG_SHIFT;
+    private static final int MSG_TOP_APP_WINDOW_CHANGED        = 50 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -160,28 +170,6 @@
         default void animateExpandSettingsPanel(String obj) { }
 
         /**
-         * Called to notify visibility flag changes.
-         * @see IStatusBar#setSystemUiVisibility(int, int, int, int, int, Rect, Rect).
-         *
-         * @param displayId The id of the display to notify.
-         * @param vis The visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will
-         *            be reported separately in fullscreenStackVis and dockedStackVis.
-         * @param fullscreenStackVis The flags which only apply in the region of the fullscreen
-         *                           stack, which is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
-         * @param dockedStackVis The flags that only apply in the region of the docked stack, which
-         *                       is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
-         * @param mask Which flags to change.
-         * @param fullscreenStackBounds The current bounds of the fullscreen stack, in screen
-         *                              coordinates.
-         * @param dockedStackBounds The current bounds of the docked stack, in screen coordinates.
-         * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
-         */
-        default void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
-                int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
-                boolean navbarColorManagedByIme) {
-        }
-
-        /**
          * Called to notify IME window status changes.
          *
          * @param displayId The id of the display to notify.
@@ -273,9 +261,9 @@
         default void showAuthenticationDialog(Bundle bundle,
                 IBiometricServiceReceiverInternal receiver, int biometricModality,
                 boolean requireConfirmation, int userId, String opPackageName) { }
-        default void onBiometricAuthenticated(boolean authenticated, String failureReason) { }
+        default void onBiometricAuthenticated() { }
         default void onBiometricHelp(String message) { }
-        default void onBiometricError(int errorCode, String error) { }
+        default void onBiometricError(int modality, int error, int vendorCode) { }
         default void hideAuthenticationDialog() { }
 
         /**
@@ -292,6 +280,28 @@
          * @see IStatusBar#onRecentsAnimationStateChanged(boolean)
          */
         default void onRecentsAnimationStateChanged(boolean running) { }
+
+        /**
+         * @see IStatusBar#onSystemBarAppearanceChanged(int, int, AppearanceRegion[], boolean).
+         */
+        default void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+                AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) { }
+
+        /**
+         * @see IStatusBar#showTransient(int, int[]).
+         */
+        default void showTransient(int displayId, @InternalInsetType int[] types) { }
+
+        /**
+         * @see IStatusBar#abortTransient(int, int[]).
+         */
+        default void abortTransient(int displayId, @InternalInsetType int[] types) { }
+
+        /**
+         * @see IStatusBar#topAppWindowChanged(int, boolean, boolean).
+         */
+        default void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+        }
     }
 
     @VisibleForTesting
@@ -456,28 +466,53 @@
         }
     }
 
+    // TODO(b/118118435): Remove this function after migration
     @Override
     public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
             int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
             boolean navbarColorManagedByIme) {
         synchronized (mLock) {
-            // Don't coalesce these, since it might have one time flags set such as
-            // STATUS_BAR_UNHIDE which might get lost.
+            final boolean hasDockedStack = !dockedStackBounds.isEmpty();
+            final boolean transientStatus = (vis & View.STATUS_BAR_TRANSIENT) != 0;
+            final boolean transientNavigation = (vis & View.NAVIGATION_BAR_TRANSIENT) != 0;
+            if (transientStatus && transientNavigation) {
+                showTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
+            } else if (transientStatus) {
+                showTransient(displayId, new int[]{TYPE_TOP_BAR});
+                abortTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
+            } else if (transientNavigation) {
+                showTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
+                abortTransient(displayId, new int[]{TYPE_TOP_BAR});
+            } else {
+                abortTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
+            }
             SomeArgs args = SomeArgs.obtain();
             args.argi1 = displayId;
-            args.argi2 = vis;
-            args.argi3 = fullscreenStackVis;
-            args.argi4 = dockedStackVis;
-            args.argi5 = mask;
-            args.argi6 = navbarColorManagedByIme ? 1 : 0;
-            args.arg1 = fullscreenStackBounds;
-            args.arg2 = dockedStackBounds;
-            mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, args).sendToTarget();
+            args.argi2 = InsetsFlags.getAppearance(vis);
+            args.argi3 = navbarColorManagedByIme ? 1 : 0;
+            final int fullscreenAppearance = InsetsFlags.getAppearance(fullscreenStackVis);
+            final int dockedAppearance = InsetsFlags.getAppearance(dockedStackVis);
+            args.arg1 = hasDockedStack
+                    ? new AppearanceRegion[]{
+                            new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
+                            new AppearanceRegion(dockedAppearance, dockedStackBounds)}
+                    : new AppearanceRegion[]{
+                            new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
+            mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
         }
     }
 
     @Override
-    public void topAppWindowChanged(int displayId, boolean menuVisible) { }
+    public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+        synchronized (mLock) {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = displayId;
+            args.argi2 = isFullscreen ? 1 : 0;
+            args.argi3 = isImmersive ? 1 : 0;
+            mHandler.obtainMessage(MSG_TOP_APP_WINDOW_CHANGED, args).sendToTarget();
+        }
+
+    }
 
     @Override
     public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
@@ -757,12 +792,9 @@
     }
 
     @Override
-    public void onBiometricAuthenticated(boolean authenticated, String failureReason) {
+    public void onBiometricAuthenticated() {
         synchronized (mLock) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = authenticated;
-            args.arg2 = failureReason;
-            mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED, args).sendToTarget();
+            mHandler.obtainMessage(MSG_BIOMETRIC_AUTHENTICATED).sendToTarget();
         }
     }
 
@@ -774,9 +806,13 @@
     }
 
     @Override
-    public void onBiometricError(int errorCode, String error) {
+    public void onBiometricError(int modality, int error, int vendorCode) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, errorCode, 0, error).sendToTarget();
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = modality;
+            args.argi2 = error;
+            args.argi3 = vendorCode;
+            mHandler.obtainMessage(MSG_BIOMETRIC_ERROR, args).sendToTarget();
         }
     }
 
@@ -827,6 +863,33 @@
         }
     }
 
+    @Override
+    public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+            AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+        synchronized (mLock) {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = displayId;
+            args.argi2 = appearance;
+            args.argi3 = navbarColorManagedByIme ? 1 : 0;
+            args.arg1 = appearanceRegions;
+            mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
+        }
+    }
+
+    @Override
+    public void showTransient(int displayId, int[] types) {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_SHOW_TRANSIENT, displayId, 0, types).sendToTarget();
+        }
+    }
+
+    @Override
+    public void abortTransient(int displayId, int[] types) {
+        synchronized (mLock) {
+            mHandler.obtainMessage(MSG_ABORT_TRANSIENT, displayId, 0, types).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         private H(Looper l) {
             super(l);
@@ -879,15 +942,6 @@
                         mCallbacks.get(i).animateExpandSettingsPanel((String) msg.obj);
                     }
                     break;
-                case MSG_SET_SYSTEMUI_VISIBILITY:
-                    args = (SomeArgs) msg.obj;
-                    for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
-                                args.argi4, args.argi5, (Rect) args.arg1, (Rect) args.arg2,
-                                args.argi6 == 1);
-                    }
-                    args.recycle();
-                    break;
                 case MSG_SHOW_IME_BUTTON:
                     args = (SomeArgs) msg.obj;
                     handleShowImeButton(args.argi1 /* displayId */, (IBinder) args.arg1 /* token */,
@@ -1045,13 +1099,9 @@
                     break;
                 }
                 case MSG_BIOMETRIC_AUTHENTICATED: {
-                    SomeArgs someArgs = (SomeArgs) msg.obj;
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onBiometricAuthenticated(
-                                (boolean) someArgs.arg1 /* authenticated */,
-                                (String) someArgs.arg2 /* failureReason */);
+                        mCallbacks.get(i).onBiometricAuthenticated();
                     }
-                    someArgs.recycle();
                     break;
                 }
                 case MSG_BIOMETRIC_HELP:
@@ -1060,9 +1110,15 @@
                     }
                     break;
                 case MSG_BIOMETRIC_ERROR:
+                    SomeArgs someArgs = (SomeArgs) msg.obj;
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).onBiometricError(msg.arg1, (String) msg.obj);
+                        mCallbacks.get(i).onBiometricError(
+                                someArgs.argi1 /* modality */,
+                                someArgs.argi2 /* error */,
+                                someArgs.argi3 /* vendorCode */
+                        );
                     }
+                    someArgs.recycle();
                     break;
                 case MSG_BIOMETRIC_HIDE:
                     for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1094,6 +1150,39 @@
                         mCallbacks.get(i).onRecentsAnimationStateChanged(msg.arg1 > 0);
                     }
                     break;
+                case MSG_SYSTEM_BAR_APPEARANCE_CHANGED:
+                    args = (SomeArgs) msg.obj;
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).onSystemBarAppearanceChanged(args.argi1, args.argi2,
+                                (AppearanceRegion[]) args.arg1, args.argi3 == 1);
+                    }
+                    args.recycle();
+                    break;
+                case MSG_SHOW_TRANSIENT: {
+                    final int displayId = msg.arg1;
+                    final int[] types = (int[]) msg.obj;
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).showTransient(displayId, types);
+                    }
+                    break;
+                }
+                case MSG_ABORT_TRANSIENT: {
+                    final int displayId = msg.arg1;
+                    final int[] types = (int[]) msg.obj;
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).abortTransient(displayId, types);
+                    }
+                    break;
+                }
+                case MSG_TOP_APP_WINDOW_CHANGED: {
+                    args = (SomeArgs) msg.obj;
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).topAppWindowChanged(
+                                args.argi1, args.argi2 != 0, args.argi3 != 0);
+                    }
+                    args.recycle();
+                    break;
+                }
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
new file mode 100644
index 0000000..341c49a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -0,0 +1,81 @@
+/*
+ * 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.systemui.statusbar;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+
+import com.android.systemui.dagger.qualifiers.BgHandler;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Class to manage simple DeviceConfig-based feature flags.
+ *
+ * To enable or disable a flag, run:
+ *
+ * {@code
+ *  $ adb shell device_config put systemui <key> <true|false>
+*  }
+ *
+ * You will probably need to restart systemui for the changes to be picked up:
+ *
+ * {@code
+ *  $ adb shell am crash com.android.systemui
+ * }
+ */
+@Singleton
+public class FeatureFlags {
+    private final Map<String, Boolean> mCachedDeviceConfigFlags = new ArrayMap<>();
+
+    @Inject
+    public FeatureFlags(@BgHandler Handler bgHandler) {
+        DeviceConfig.addOnPropertiesChangedListener(
+                "systemui",
+                new HandlerExecutor(bgHandler),
+                this::onPropertiesChanged);
+    }
+
+    public boolean isNewNotifPipelineEnabled() {
+        return getDeviceConfigFlag("notification.newpipeline.enabled", false);
+    }
+
+    private void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+        synchronized (mCachedDeviceConfigFlags) {
+            for (String key : properties.getKeyset()) {
+                mCachedDeviceConfigFlags.remove(key);
+            }
+        }
+    }
+
+    private boolean getDeviceConfigFlag(String key, boolean defaultValue) {
+        synchronized (mCachedDeviceConfigFlags) {
+            Boolean flag = mCachedDeviceConfigFlags.get(key);
+            if (flag == null) {
+                flag = DeviceConfig.getBoolean("systemui", key, defaultValue);
+                mCachedDeviceConfigFlags.put(key, flag);
+            }
+            return flag;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 5144a95..1f38904 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -18,7 +18,6 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
 import static com.android.systemui.SysUiServiceProvider.getComponent;
 
 import android.content.Context;
@@ -38,6 +37,7 @@
 import com.android.internal.statusbar.RegisterStatusBarResult;
 import com.android.systemui.Dependency;
 import com.android.systemui.assist.AssistHandleViewController;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.phone.AutoHideController;
@@ -48,7 +48,6 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 
@@ -67,7 +66,7 @@
     SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();
 
     @Inject
-    public NavigationBarController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
+    public NavigationBarController(Context context, @MainHandler Handler handler) {
         mContext = context;
         mHandler = handler;
         mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
@@ -156,7 +155,7 @@
                             Dependency.get(NotificationRemoteInputManager.class),
                             Dependency.get(IWindowManager.class));
             navBar.setAutoHideController(autoHideController);
-            navBar.restoreSystemUiVisibilityState();
+            navBar.restoreAppearanceAndTransientState();
             mNavigationBars.append(displayId, navBar);
 
             if (result != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 6ffea79..7adf7af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -323,7 +323,7 @@
             exceedsPriorityThreshold = entry.getBucket() != BUCKET_SILENT;
         } else {
             exceedsPriorityThreshold =
-                    !getEntryManager().getNotificationData().isAmbient(entry.key);
+                    !getEntryManager().getNotificationData().isAmbient(entry.getKey());
         }
         return mShowLockscreenNotifications && exceedsPriorityThreshold;
     }
@@ -445,15 +445,15 @@
 
     /** @return true if the entry needs redaction when on the lockscreen. */
     public boolean needsRedaction(NotificationEntry ent) {
-        int userId = ent.notification.getUserId();
+        int userId = ent.getSbn().getUserId();
 
         boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
         boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
         boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
 
         boolean notificationRequestsRedaction =
-                ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE;
-        boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey());
+                ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+        boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
 
         return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 3616b54..0988e34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -204,7 +204,7 @@
                     NotificationEntry entry,
                     NotificationVisibility visibility,
                     boolean removedByUser) {
-                onNotificationRemoved(entry.key);
+                onNotificationRemoved(entry.getKey());
             }
         });
 
@@ -284,7 +284,7 @@
 
                 if (entry.isMediaNotification()) {
                     final MediaSession.Token token =
-                            entry.notification.getNotification().extras.getParcelable(
+                            entry.getSbn().getNotification().extras.getParcelable(
                                     Notification.EXTRA_MEDIA_SESSION);
                     if (token != null) {
                         MediaController aController = new MediaController(mContext, token);
@@ -292,7 +292,7 @@
                                 getMediaControllerPlaybackState(aController)) {
                             if (DEBUG_MEDIA) {
                                 Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching "
-                                        + entry.notification.getKey());
+                                        + entry.getSbn().getKey());
                             }
                             mediaNotification = entry;
                             controller = aController;
@@ -321,10 +321,10 @@
 
                             for (int i = 0; i < N; i++) {
                                 final NotificationEntry entry = activeNotifications.get(i);
-                                if (entry.notification.getPackageName().equals(pkg)) {
+                                if (entry.getSbn().getPackageName().equals(pkg)) {
                                     if (DEBUG_MEDIA) {
                                         Log.v(TAG, "DEBUG_MEDIA: found controller matching "
-                                                + entry.notification.getKey());
+                                                + entry.getSbn().getKey());
                                     }
                                     controller = aController;
                                     mediaNotification = entry;
@@ -351,8 +351,8 @@
             }
 
             if (mediaNotification != null
-                    && !mediaNotification.notification.getKey().equals(mMediaNotificationKey)) {
-                mMediaNotificationKey = mediaNotification.notification.getKey();
+                    && !mediaNotification.getSbn().getKey().equals(mMediaNotificationKey)) {
+                mMediaNotificationKey = mediaNotification.getSbn().getKey();
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
                             + mMediaNotificationKey);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index c9050d4..c838ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -17,8 +17,6 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -52,6 +50,7 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -69,7 +68,6 @@
 import java.util.Set;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 import dagger.Lazy;
@@ -262,7 +260,7 @@
             NotificationEntryManager notificationEntryManager,
             Lazy<ShadeController> shadeController,
             StatusBarStateController statusBarStateController,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+            @MainHandler Handler mainHandler) {
         mContext = context;
         mLockscreenUserManager = lockscreenUserManager;
         mSmartReplyController = smartReplyController;
@@ -293,7 +291,7 @@
                 mSmartReplyController.stopSending(entry);
 
                 if (removedByUser && entry != null) {
-                    onPerformRemoveNotification(entry, entry.key);
+                    onPerformRemoveNotification(entry, entry.getKey());
                 }
             }
         });
@@ -307,8 +305,8 @@
             @Override
             public void onRemoteInputSent(NotificationEntry entry) {
                 if (FORCE_REMOTE_INPUT_HISTORY
-                        && isNotificationKeptForRemoteInputHistory(entry.key)) {
-                    mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+                        && isNotificationKeptForRemoteInputHistory(entry.getKey())) {
+                    mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
                 } else if (mEntriesKeptForRemoteInputActive.contains(entry)) {
                     // We're currently holding onto this notification, but from the apps point of
                     // view it is already canceled, so we'll need to cancel it on the apps behalf
@@ -316,18 +314,18 @@
                     // bit.
                     mMainHandler.postDelayed(() -> {
                         if (mEntriesKeptForRemoteInputActive.remove(entry)) {
-                            mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+                            mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
                         }
                     }, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
                 }
                 try {
-                    mBarService.onNotificationDirectReplied(entry.notification.getKey());
+                    mBarService.onNotificationDirectReplied(entry.getSbn().getKey());
                     if (entry.editedSuggestionInfo != null) {
                         boolean modifiedBeforeSending =
                                 !TextUtils.equals(entry.remoteInputText,
                                         entry.editedSuggestionInfo.originalText);
                         mBarService.onNotificationSmartReplySent(
-                                entry.notification.getKey(),
+                                entry.getSbn().getKey(),
                                 entry.editedSuggestionInfo.index,
                                 entry.editedSuggestionInfo.originalText,
                                 NotificationLogger
@@ -487,7 +485,7 @@
             NotificationEntry entry = mEntriesKeptForRemoteInputActive.valueAt(i);
             mRemoteInputController.removeRemoteInput(entry, null);
             if (mNotificationLifetimeFinishedCallback != null) {
-                mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.key);
+                mNotificationLifetimeFinishedCallback.onSafeToRemove(entry.getKey());
             }
         }
         mEntriesKeptForRemoteInputActive.clear();
@@ -501,14 +499,15 @@
         if (!FORCE_REMOTE_INPUT_HISTORY) {
             return false;
         }
-        return (mRemoteInputController.isSpinning(entry.key) || entry.hasJustSentRemoteInput());
+        return (mRemoteInputController.isSpinning(entry.getKey())
+                || entry.hasJustSentRemoteInput());
     }
 
     public boolean shouldKeepForSmartReplyHistory(NotificationEntry entry) {
         if (!FORCE_REMOTE_INPUT_HISTORY) {
             return false;
         }
-        return mSmartReplyController.isSendingSmartReply(entry.key);
+        return mSmartReplyController.isSendingSmartReply(entry.getKey());
     }
 
     public void checkRemoteInputOutside(MotionEvent event) {
@@ -529,7 +528,7 @@
     @VisibleForTesting
     StatusBarNotification rebuildNotificationWithRemoteInput(NotificationEntry entry,
             CharSequence remoteInputText, boolean showSpinner) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         Notification.Builder b = Notification.Builder
                 .recoverBuilder(mContext, sbn.getNotification().clone());
@@ -637,12 +636,12 @@
 
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
                     Log.d(TAG, "Keeping notification around after sending remote input "
-                            + entry.key);
+                            + entry.getKey());
                 }
 
-                mKeysKeptForRemoteInputHistory.add(entry.key);
+                mKeysKeptForRemoteInputHistory.add(entry.getKey());
             } else {
-                mKeysKeptForRemoteInputHistory.remove(entry.key);
+                mKeysKeptForRemoteInputHistory.remove(entry.getKey());
             }
         }
     }
@@ -675,12 +674,12 @@
 
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
                     Log.d(TAG, "Keeping notification around after sending smart reply "
-                            + entry.key);
+                            + entry.getKey());
                 }
 
-                mKeysKeptForRemoteInputHistory.add(entry.key);
+                mKeysKeptForRemoteInputHistory.add(entry.getKey());
             } else {
-                mKeysKeptForRemoteInputHistory.remove(entry.key);
+                mKeysKeptForRemoteInputHistory.remove(entry.getKey());
                 mSmartReplyController.stopSending(entry);
             }
         }
@@ -701,7 +700,7 @@
             if (shouldExtend) {
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
                     Log.d(TAG, "Keeping notification around while remote input active "
-                            + entry.key);
+                            + entry.getKey());
                 }
                 mEntriesKeptForRemoteInputActive.add(entry);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
index 266fe8d..564d8bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -54,7 +54,7 @@
     public static NotificationUiAdjustment extractFromNotificationEntry(
             NotificationEntry entry) {
         return new NotificationUiAdjustment(
-                entry.key, entry.getSmartActions(), entry.getSmartReplies());
+                entry.getKey(), entry.getSmartActions(), entry.getSmartReplies());
     }
 
     public static boolean needReinflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 50d9bae..d6b87af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -16,19 +16,19 @@
 
 package com.android.systemui.statusbar;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.systemui.R;
 import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -47,7 +47,6 @@
 import java.util.Stack;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 import dagger.Lazy;
@@ -88,6 +87,7 @@
     private final BubbleController mBubbleController;
     private final DynamicPrivacyController mDynamicPrivacyController;
     private final KeyguardBypassController mBypassController;
+    private final Context mContext;
 
     private NotificationPresenter mPresenter;
     private NotificationListContainer mListContainer;
@@ -99,8 +99,7 @@
     private boolean mIsHandleDynamicPrivacyChangeScheduled;
 
     @Inject
-    public NotificationViewHierarchyManager(Context context,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler,
+    public NotificationViewHierarchyManager(Context context, @MainHandler Handler mainHandler,
             NotificationLockscreenUserManager notificationLockscreenUserManager,
             NotificationGroupManager groupManager,
             VisualStabilityManager visualStabilityManager,
@@ -110,6 +109,7 @@
             KeyguardBypassController bypassController,
             BubbleController bubbleController,
             DynamicPrivacyController privacyController) {
+        mContext = context;
         mHandler = mainHandler;
         mLockscreenUserManager = notificationLockscreenUserManager;
         mBypassController = bypassController;
@@ -146,14 +146,18 @@
         final int N = activeNotifications.size();
         for (int i = 0; i < N; i++) {
             NotificationEntry ent = activeNotifications.get(i);
+            int flag = Settings.System.getInt(mContext.getContentResolver(),
+                    "qs_media_player", 0);
+            boolean hideMedia = (flag == 1);
             if (ent.isRowDismissed() || ent.isRowRemoved()
-                    || mBubbleController.isBubbleNotificationSuppressedFromShade(ent.key)) {
+                    || (ent.isMediaNotification() && hideMedia)
+                    || mBubbleController.isBubbleNotificationSuppressedFromShade(ent.getKey())) {
                 // we don't want to update removed notifications because they could
                 // temporarily become children if they were isolated before.
                 continue;
             }
 
-            int userId = ent.notification.getUserId();
+            int userId = ent.getSbn().getUserId();
 
             // Display public version of the notification if we need to redact.
             // TODO: This area uses a lot of calls into NotificationLockscreenUserManager.
@@ -174,8 +178,8 @@
                     currentUserId);
             ent.setSensitive(sensitive, deviceSensitive);
             ent.getRow().setNeedsRedaction(needsRedaction);
-            if (mGroupManager.isChildInGroupWithSummary(ent.notification)) {
-                NotificationEntry summary = mGroupManager.getGroupSummary(ent.notification);
+            if (mGroupManager.isChildInGroupWithSummary(ent.getSbn())) {
+                NotificationEntry summary = mGroupManager.getGroupSummary(ent.getSbn());
                 List<ExpandableNotificationRow> orderedChildren =
                         mTmpChildOrderMap.get(summary.getRow());
                 if (orderedChildren == null) {
@@ -382,7 +386,7 @@
             ExpandableNotificationRow row = stack.pop();
             NotificationEntry entry = row.getEntry();
             boolean isChildNotification =
-                    mGroupManager.isChildInGroupWithSummary(entry.notification);
+                    mGroupManager.isChildInGroupWithSummary(entry.getSbn());
 
             row.setOnKeyguard(onKeyguard);
 
@@ -394,15 +398,15 @@
                         && !row.isLowPriority()));
             }
 
-            int userId = entry.notification.getUserId();
+            int userId = entry.getSbn().getUserId();
             boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
-                    entry.notification) && !entry.isRowRemoved();
+                    entry.getSbn()) && !entry.isRowRemoved();
             boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry);
             if (!showOnKeyguard) {
                 // min priority notifications should show if their summary is showing
-                if (mGroupManager.isChildInGroupWithSummary(entry.notification)) {
+                if (mGroupManager.isChildInGroupWithSummary(entry.getSbn())) {
                     NotificationEntry summary = mGroupManager.getLogicalGroupSummary(
-                            entry.notification);
+                            entry.getSbn());
                     if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) {
                         showOnKeyguard = true;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 736b9eb..7bdb21d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -58,9 +58,9 @@
     public void smartReplySent(NotificationEntry entry, int replyIndex, CharSequence reply,
             int notificationLocation, boolean modifiedBeforeSending) {
         mCallback.onSmartReplySent(entry, reply);
-        mSendingKeys.add(entry.key);
+        mSendingKeys.add(entry.getKey());
         try {
-            mBarService.onNotificationSmartReplySent(entry.notification.getKey(), replyIndex, reply,
+            mBarService.onNotificationSmartReplySent(entry.getSbn().getKey(), replyIndex, reply,
                     notificationLocation, modifiedBeforeSending);
         } catch (RemoteException e) {
             // Nothing to do, system going down
@@ -74,14 +74,14 @@
             NotificationEntry entry, int actionIndex, Notification.Action action,
             boolean generatedByAssistant) {
         final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
-        final int rank = mEntryManager.getNotificationData().getRank(entry.key);
+        final int rank = mEntryManager.getNotificationData().getRank(entry.getKey());
         NotificationVisibility.NotificationLocation location =
                 NotificationLogger.getNotificationLocation(entry);
         final NotificationVisibility nv = NotificationVisibility.obtain(
-                entry.key, rank, count, true, location);
+                entry.getKey(), rank, count, true, location);
         try {
             mBarService.onNotificationActionClick(
-                    entry.key, actionIndex, action, nv, generatedByAssistant);
+                    entry.getKey(), actionIndex, action, nv, generatedByAssistant);
         } catch (RemoteException e) {
             // Nothing to do, system going down
         }
@@ -101,7 +101,7 @@
     public void smartSuggestionsAdded(final NotificationEntry entry, int replyCount,
             int actionCount, boolean generatedByAssistant, boolean editBeforeSending) {
         try {
-            mBarService.onNotificationSmartSuggestionsAdded(entry.notification.getKey(), replyCount,
+            mBarService.onNotificationSmartSuggestionsAdded(entry.getSbn().getKey(), replyCount,
                     actionCount, generatedByAssistant, editBeforeSending);
         } catch (RemoteException e) {
             // Nothing to do, system going down
@@ -110,7 +110,7 @@
 
     public void stopSending(final NotificationEntry entry) {
         if (entry != null) {
-            mSendingKeys.remove(entry.notification.getKey());
+            mSendingKeys.remove(entry.getSbn().getKey());
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 8b9268e..e81e5ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -21,7 +21,6 @@
 import android.text.format.DateFormat;
 import android.util.FloatProperty;
 import android.util.Log;
-import android.view.View;
 import android.view.animation.Interpolator;
 
 import com.android.internal.annotations.GuardedBy;
@@ -80,9 +79,14 @@
     private HistoricalState[] mHistoricalRecords = new HistoricalState[HISTORY_SIZE];
 
     /**
-     * Current SystemUiVisibility
+     * If any of the system bars is hidden.
      */
-    private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+    private boolean mIsFullscreen = false;
+
+    /**
+     * If the navigation bar can stay hidden when the display gets tapped.
+     */
+    private boolean mIsImmersive = false;
 
     /**
      * If the device is currently pulsing (AOD2).
@@ -320,12 +324,13 @@
     }
 
     @Override
-    public void setSystemUiVisibility(int visibility) {
-        if (mSystemUiVisibility != visibility) {
-            mSystemUiVisibility = visibility;
+    public void setFullscreenState(boolean isFullscreen, boolean isImmersive) {
+        if (mIsFullscreen != isFullscreen || mIsImmersive != isImmersive) {
+            mIsFullscreen = isFullscreen;
+            mIsImmersive = isImmersive;
             synchronized (mListeners) {
                 for (RankedListener rl : new ArrayList<>(mListeners)) {
-                    rl.mListener.onSystemUiVisibilityChanged(mSystemUiVisibility);
+                    rl.mListener.onFullscreenStateChanged(isFullscreen, isImmersive);
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
index 2ad979ab..07b3550 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
@@ -111,9 +111,9 @@
     boolean isKeyguardRequested();
 
     /**
-     * Set systemui visibility
+     * Set the fullscreen state
      */
-    void setSystemUiVisibility(int visibility);
+    void setFullscreenState(boolean isFullscreen, boolean isImmersive);
 
     /**
      * Set pulsing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index f284f73..53fbe5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -155,7 +156,8 @@
                                     focusedStack.configuration.windowConfiguration
                                             .getWindowingMode();
                             if (windowingMode == WINDOWING_MODE_FULLSCREEN
-                                    || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+                                    || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+                                    || windowingMode == WINDOWING_MODE_FREEFORM) {
                                 checkAndPostForStack(focusedStack, notifs, noMan, pm);
                             }
                         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java
new file mode 100644
index 0000000..31921a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NewNotifPipeline.java
@@ -0,0 +1,49 @@
+/*
+ * 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.systemui.statusbar.notification;
+
+import android.util.Log;
+
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Initialization code for the new notification pipeline.
+ */
+@Singleton
+public class NewNotifPipeline {
+    private final NotifCollection mNotifCollection;
+
+    @Inject
+    public NewNotifPipeline(
+            NotifCollection notifCollection) {
+        mNotifCollection = notifCollection;
+    }
+
+    /** Hooks the new pipeline up to NotificationManager */
+    public void initialize(
+            NotificationListener notificationService) {
+        mNotifCollection.attach(notificationService);
+
+        Log.d(TAG, "Notif pipeline initialized");
+    }
+
+    private static final String TAG = "NewNotifPipeline";
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineInitializer.java
deleted file mode 100644
index df70828..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineInitializer.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.systemui.statusbar.notification;
-
-import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
-
-import com.android.systemui.statusbar.NotificationListener;
-
-import javax.inject.Inject;
-
-/**
- * Initialization code for the new notification pipeline.
- */
-public class NotifPipelineInitializer {
-
-    @Inject
-    public NotifPipelineInitializer() {
-    }
-
-    public void initialize(
-            NotificationListener notificationService) {
-
-        // TODO Put real code here
-        notificationService.setDownstreamListener(new NotificationListener.NotifServiceListener() {
-            @Override
-            public void onNotificationPosted(StatusBarNotification sbn,
-                    NotificationListenerService.RankingMap rankingMap) {
-                Log.d(TAG, "onNotificationPosted " + sbn.getKey());
-            }
-
-            @Override
-            public void onNotificationRemoved(StatusBarNotification sbn,
-                    NotificationListenerService.RankingMap rankingMap) {
-                Log.d(TAG, "onNotificationRemoved " + sbn.getKey());
-            }
-
-            @Override
-            public void onNotificationRemoved(StatusBarNotification sbn,
-                    NotificationListenerService.RankingMap rankingMap, int reason) {
-                Log.d(TAG, "onNotificationRemoved " + sbn.getKey());
-            }
-
-            @Override
-            public void onNotificationRankingUpdate(
-                    NotificationListenerService.RankingMap rankingMap) {
-                Log.d(TAG, "onNotificationRankingUpdate");
-            }
-        });
-    }
-
-    private static final String TAG = "NotifInitializer";
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index d71d407..005f01d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -80,7 +80,7 @@
                     NotificationEntry entry,
                     NotificationVisibility visibility,
                     boolean removedByUser) {
-                stopAlerting(entry.key);
+                stopAlerting(entry.getKey());
             }
         });
     }
@@ -104,7 +104,7 @@
                 mHeadsUpManager.showNotification(entry);
                 if (!mShadeController.get().isDozing()) {
                     // Mark as seen immediately
-                    setNotificationShown(entry.notification);
+                    setNotificationShown(entry.getSbn());
                 }
             } else {
                 entry.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
@@ -113,16 +113,16 @@
     }
 
     private void updateAlertState(NotificationEntry entry) {
-        boolean alertAgain = alertAgain(entry, entry.notification.getNotification());
+        boolean alertAgain = alertAgain(entry, entry.getSbn().getNotification());
         boolean shouldAlert;
         shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
-        final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.key);
+        final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.getKey());
         if (wasAlerting) {
             if (shouldAlert) {
-                mHeadsUpManager.updateNotification(entry.key, alertAgain);
-            } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.key)) {
+                mHeadsUpManager.updateNotification(entry.getKey(), alertAgain);
+            } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.getKey())) {
                 // We don't want this to be interrupting anymore, let's remove it
-                mHeadsUpManager.removeNotification(entry.key, false /* removeImmediately */);
+                mHeadsUpManager.removeNotification(entry.getKey(), false /* removeImmediately */);
             }
         } else if (shouldAlert && alertAgain) {
             // This notification was updated to be alerting, show it!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index dfc6450..df78fa3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -20,12 +20,12 @@
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 
-import androidx.annotation.NonNull;
-
 /**
  * Listener interface for changes sent by NotificationEntryManager.
  */
@@ -37,13 +37,6 @@
     default void onPendingEntryAdded(NotificationEntry entry) {
     }
 
-    // TODO: Combine this with onPreEntryUpdated into "onBeforeEntryFiltered" or similar
-    /**
-     * Called when a new entry is created but before it has been filtered or displayed to the user.
-     */
-    default void onBeforeNotificationAdded(NotificationEntry entry) {
-    }
-
     /**
      * Called when a new entry is created.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 01c79b3..bde097a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -110,7 +110,7 @@
             pw.println("null");
         } else {
             for (NotificationEntry entry : mPendingNotifications.values()) {
-                pw.println(entry.notification);
+                pw.println(entry.getSbn());
             }
         }
         pw.println("  Lifetime-extended notifications:");
@@ -119,14 +119,16 @@
         } else {
             for (Map.Entry<NotificationEntry, NotificationLifetimeExtender> entry
                     : mRetainedNotifications.entrySet()) {
-                pw.println("    " + entry.getKey().notification + " retained by "
+                pw.println("    " + entry.getKey().getSbn() + " retained by "
                         + entry.getValue().getClass().getName());
             }
         }
     }
 
     @Inject
-    public NotificationEntryManager(NotificationData notificationData, NotifLog notifLog) {
+    public NotificationEntryManager(
+            NotificationData notificationData,
+            NotifLog notifLog) {
         mNotificationData = notificationData;
         mNotifLog = notifLog;
     }
@@ -136,6 +138,14 @@
         mNotificationEntryListeners.add(listener);
     }
 
+    /**
+     * Removes a {@link NotificationEntryListener} previously registered via
+     * {@link #addNotificationEntryListener(NotificationEntryListener)}.
+     */
+    public void removeNotificationEntryListener(NotificationEntryListener listener) {
+        mNotificationEntryListeners.remove(listener);
+    }
+
     /** Sets the {@link NotificationRemoveInterceptor}. */
     public void setNotificationRemoveInterceptor(NotificationRemoveInterceptor interceptor) {
         mRemoveInterceptor = interceptor;
@@ -212,13 +222,13 @@
             NotificationEntry entry = mPendingNotifications.get(key);
             entry.abortTask();
             mPendingNotifications.remove(key);
-            mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.sbn(), null,
+            mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.getSbn(), null,
                     "PendingNotification aborted. " + reason);
         }
         NotificationEntry addedEntry = mNotificationData.get(key);
         if (addedEntry != null) {
             addedEntry.abortTask();
-            mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.sbn(),
+            mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.getSbn(),
                     null, reason);
         }
     }
@@ -242,19 +252,16 @@
     @Override
     public void onAsyncInflationFinished(NotificationEntry entry,
             @InflationFlag int inflatedFlags) {
-        mPendingNotifications.remove(entry.key);
+        mPendingNotifications.remove(entry.getKey());
         // If there was an async task started after the removal, we don't want to add it back to
         // the list, otherwise we might get leaks.
         if (!entry.isRowRemoved()) {
-            boolean isNew = mNotificationData.get(entry.key) == null;
+            boolean isNew = mNotificationData.get(entry.getKey()) == null;
             if (isNew) {
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onEntryInflated(entry, inflatedFlags);
                 }
                 mNotificationData.add(entry);
-                for (NotificationEntryListener listener : mNotificationEntryListeners) {
-                    listener.onBeforeNotificationAdded(entry);
-                }
                 updateNotifications("onAsyncInflationFinished");
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onNotificationAdded(entry);
@@ -302,7 +309,7 @@
                         lifetimeExtended = true;
                         mNotifLog.log(
                                 NotifEvent.LIFETIME_EXTENDED,
-                                pendingEntry.sbn(),
+                                pendingEntry.getSbn(),
                                 "pendingEntry extendedBy=" + extender.toString());
                     }
                 }
@@ -325,7 +332,7 @@
                         lifetimeExtended = true;
                         mNotifLog.log(
                                 NotifEvent.LIFETIME_EXTENDED,
-                                entry.sbn(),
+                                entry.getSbn(),
                                 "entry extendedBy=" + extender.toString());
                         break;
                     }
@@ -350,7 +357,7 @@
                 Dependency.get(LeakDetector.class).trackGarbage(entry);
                 removedByUser |= entryDismissed;
 
-                mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.sbn(),
+                mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.getSbn(),
                         "removedByUser=" + removedByUser);
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onEntryRemoved(entry, visibility, removedByUser);
@@ -372,7 +379,7 @@
     private void handleGroupSummaryRemoved(String key) {
         NotificationEntry entry = mNotificationData.get(key);
         if (entry != null && entry.rowExists() && entry.isSummaryWithChildren()) {
-            if (entry.notification.getOverrideGroupKey() != null && !entry.isRowDismissed()) {
+            if (entry.getSbn().getOverrideGroupKey() != null && !entry.isRowDismissed()) {
                 // We don't want to remove children for autobundled notifications as they are not
                 // always cancelled. We only remove them if they were dismissed by the user.
                 return;
@@ -383,7 +390,7 @@
             }
             for (int i = 0; i < childEntries.size(); i++) {
                 NotificationEntry childEntry = childEntries.get(i);
-                boolean isForeground = (entry.notification.getNotification().flags
+                boolean isForeground = (entry.getSbn().getNotification().flags
                         & Notification.FLAG_FOREGROUND_SERVICE) != 0;
                 boolean keepForReply =
                         getRemoteInputManager().shouldKeepForRemoteInputHistory(childEntry)
@@ -421,7 +428,7 @@
 
         abortExistingInflation(key, "addNotification");
         mPendingNotifications.put(key, entry);
-        mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.sbn());
+        mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.getSbn());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPendingEntryAdded(entry);
         }
@@ -453,7 +460,7 @@
         cancelLifetimeExtension(entry);
 
         mNotificationData.update(entry, ranking, notification, "updateNotificationInternal");
-        mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.sbn(), entry.ranking());
+        mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.getSbn(), entry.getRanking());
         for (NotificationEntryListener listener : mNotificationEntryListeners) {
             listener.onPreEntryUpdated(entry);
         }
@@ -507,8 +514,8 @@
         for (NotificationEntry entry : entries) {
             NotificationUiAdjustment adjustment =
                     NotificationUiAdjustment.extractFromNotificationEntry(entry);
-            oldAdjustments.put(entry.key, adjustment);
-            oldImportances.put(entry.key, entry.getImportance());
+            oldAdjustments.put(entry.getKey(), adjustment);
+            oldImportances.put(entry.getKey(), entry.getImportance());
         }
 
         // Populate notification entries from the new rankings.
@@ -519,8 +526,8 @@
         for (NotificationEntry entry : entries) {
             requireBinder().onNotificationRankingUpdated(
                     entry,
-                    oldImportances.get(entry.key),
-                    oldAdjustments.get(entry.key),
+                    oldImportances.get(entry.getKey()),
+                    oldAdjustments.get(entry.getKey()),
                     NotificationUiAdjustment.extractFromNotificationEntry(entry));
         }
 
@@ -538,7 +545,7 @@
         }
         for (NotificationEntry pendingNotification : mPendingNotifications.values()) {
             Ranking ranking = new Ranking();
-            if (rankingMap.getRanking(pendingNotification.key(), ranking)) {
+            if (rankingMap.getRanking(pendingNotification.getKey(), ranking)) {
                 pendingNotification.setRanking(ranking);
             }
         }
@@ -553,6 +560,18 @@
         return mPendingNotifications.values();
     }
 
+    /**
+     * Gets the pending or visible notification entry with the given key. Returns null if
+     * notification doesn't exist.
+     */
+    public NotificationEntry getPendingOrCurrentNotif(String key) {
+        if (mPendingNotifications.containsKey(key)) {
+            return mPendingNotifications.get(key);
+        } else {
+            return mNotificationData.get(key);
+        }
+    }
+
     private void extendLifetime(NotificationEntry entry, NotificationLifetimeExtender extender) {
         NotificationLifetimeExtender activeExtender = mRetainedNotifications.get(entry);
         if (activeExtender != null && activeExtender != extender) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index 5a0b88c..b116409 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -85,7 +85,7 @@
      * @return true if the provided notification should NOT be shown right now.
      */
     public boolean shouldFilterOut(NotificationEntry entry) {
-        final StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.getSbn();
         if (!(getEnvironment().isDeviceProvisioned()
                 || showNotificationEvenIfUnprovisioned(sbn))) {
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index eadec6a..7d09932 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -164,7 +164,7 @@
      * @return true if the entry should bubble up, false otherwise
      */
     public boolean shouldBubbleUp(NotificationEntry entry) {
-        final StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.getSbn();
 
         if (!canAlertCommon(entry)) {
             return false;
@@ -216,7 +216,7 @@
     }
 
     private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (!mUseHeadsUp) {
             if (DEBUG_HEADS_UP) {
@@ -289,7 +289,7 @@
      * @return true if the entry should ambient pulse, false otherwise
      */
     private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
             if (DEBUG_HEADS_UP) {
@@ -336,7 +336,7 @@
      */
     @VisibleForTesting
     public boolean canAlertCommon(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (mNotificationFilter.shouldFilterOut(entry)) {
             if (DEBUG || DEBUG_HEADS_UP) {
@@ -363,7 +363,7 @@
      */
     @VisibleForTesting
     public boolean canAlertAwakeCommon(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         if (mPresenter.isDeviceInVrMode()) {
             if (DEBUG_HEADS_UP) {
@@ -423,7 +423,7 @@
      * @return {@code true} if we should launch the full screen intent
      */
     public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
-        return entry.notification.getNotification().fullScreenIntent != null
+        return entry.getSbn().getNotification().fullScreenIntent != null
             && (!shouldHeadsUp(entry)
                 || mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
index 970cbf9..2eefe29 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -18,10 +18,6 @@
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
-
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -70,11 +66,6 @@
                 boolean removedByUser) {
             mListContainer.cleanUpViewStateForEntry(entry);
         }
-
-        @Override
-        public void onBeforeNotificationAdded(NotificationEntry entry) {
-            tagForeground(entry.notification);
-        }
     };
 
     private final DeviceProvisionedListener mDeviceProvisionedListener =
@@ -84,29 +75,4 @@
                     mEntryManager.updateNotifications("device provisioned changed");
                 }
             };
-
-    // TODO: This method is horrifically inefficient
-    private void tagForeground(StatusBarNotification notification) {
-        ArraySet<Integer> activeOps =
-                mForegroundServiceController.getAppOps(
-                        notification.getUserId(), notification.getPackageName());
-        if (activeOps != null) {
-            int len = activeOps.size();
-            for (int i = 0; i < len; i++) {
-                updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
-                        notification.getPackageName(), true);
-            }
-        }
-    }
-
-    /** When an app op changes, propagate that change to notifications. */
-    public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
-        String foregroundKey =
-                mForegroundServiceController.getStandardLayoutKey(UserHandle.getUserId(uid), pkg);
-        if (foregroundKey != null) {
-            mEntryManager
-                    .getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
-            mEntryManager.updateNotifications("app opp changed pkg=" + pkg);
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
index 480cb78..0095511 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -66,7 +66,7 @@
 private fun usePeopleFiltering(proxy: DeviceConfigProxy): Boolean {
     if (sUsePeopleFiltering == null) {
         sUsePeopleFiltering = proxy.getBoolean(
-                DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, false)
+                DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, true)
     }
 
     return sUsePeopleFiltering!!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index 6fe4abe..1daf484 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.notification;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.os.Handler;
 import android.os.SystemClock;
 import android.view.View;
@@ -25,6 +23,7 @@
 import androidx.collection.ArraySet;
 
 import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -35,7 +34,6 @@
 import java.util.ArrayList;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -64,8 +62,7 @@
 
     @Inject
     public VisualStabilityManager(
-            NotificationEntryManager notificationEntryManager,
-            @Named(MAIN_HANDLER_NAME) Handler handler) {
+            NotificationEntryManager notificationEntryManager, @MainHandler Handler handler) {
 
         mHandler = handler;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
new file mode 100644
index 0000000..ecce6ea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
@@ -0,0 +1,38 @@
+/*
+ * 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.systemui.statusbar.notification.collection;
+
+import android.service.notification.NotificationStats.DismissalSentiment;
+import android.service.notification.NotificationStats.DismissalSurface;
+
+import com.android.internal.statusbar.NotificationVisibility;
+
+/** Information that must be supplied when dismissing a notification on the behalf of the user. */
+public class DismissedByUserStats {
+    public final @DismissalSurface int dismissalSurface;
+    public final @DismissalSentiment int dismissalSentiment;
+    public final NotificationVisibility notificationVisibility;
+
+    public DismissedByUserStats(
+            @DismissalSurface int dismissalSurface,
+            @DismissalSentiment int dismissalSentiment,
+            NotificationVisibility notificationVisibility) {
+        this.dismissalSurface = dismissalSurface;
+        this.dismissalSentiment = dismissalSentiment;
+        this.notificationVisibility = notificationVisibility;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
new file mode 100644
index 0000000..b551352
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -0,0 +1,426 @@
+/*
+ * 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.systemui.statusbar.notification.collection;
+
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+import static android.service.notification.NotificationListenerService.REASON_ERROR;
+import static android.service.notification.NotificationListenerService.REASON_GROUP_OPTIMIZATION;
+import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_SUSPENDED;
+import static android.service.notification.NotificationListenerService.REASON_PROFILE_TURNED_OFF;
+import static android.service.notification.NotificationListenerService.REASON_SNOOZED;
+import static android.service.notification.NotificationListenerService.REASON_TIMEOUT;
+import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
+import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.IntDef;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.util.Assert;
+
+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.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Keeps a record of all of the "active" notifications, i.e. the notifications that are currently
+ * posted to the phone. This collection is unsorted, ungrouped, and unfiltered. Just because a
+ * notification appears in this collection doesn't mean that it's currently present in the shade
+ * (notifications can be hidden for a variety of reasons). Code that cares about what notifications
+ * are *visible* right now should register listeners later in the pipeline.
+ *
+ * Each notification is represented by a {@link NotificationEntry}, which is itself made up of two
+ * parts: a {@link StatusBarNotification} and a {@link Ranking}. When notifications are updated,
+ * their underlying SBNs and Rankings are swapped out, but the enclosing NotificationEntry (and its
+ * associated key) remain the same. In general, an SBN can only be updated when the notification is
+ * reposted by the source app; Rankings are updated much more often, usually every time there is an
+ * update from any kind from NotificationManager.
+ *
+ * In general, this collection closely mirrors the list maintained by NotificationManager, but it
+ * can occasionally diverge due to lifetime extenders (see
+ * {@link #addNotificationLifetimeExtender(NotifLifetimeExtender)}).
+ *
+ * Interested parties can register listeners
+ * ({@link #addCollectionListener(NotifCollectionListener)}) to be informed when notifications are
+ * added, updated, or removed.
+ */
+@MainThread
+@Singleton
+public class NotifCollection {
+    private final IStatusBarService mStatusBarService;
+
+    private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
+    private final Collection<NotificationEntry> mReadOnlyNotificationSet =
+            Collections.unmodifiableCollection(mNotificationSet.values());
+
+    @Nullable private NotifListBuilder mListBuilder;
+    private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
+    private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
+
+    private boolean mAttached = false;
+    private boolean mAmDispatchingToOtherCode;
+
+    @Inject
+    public NotifCollection(IStatusBarService statusBarService) {
+        Assert.isMainThread();
+        mStatusBarService = statusBarService;
+    }
+
+    /** Initializes the NotifCollection and registers it to receive notification events. */
+    public void attach(NotificationListener listenerService) {
+        Assert.isMainThread();
+        if (mAttached) {
+            throw new RuntimeException("attach() called twice");
+        }
+        mAttached = true;
+
+        listenerService.setDownstreamListener(mNotifServiceListener);
+    }
+
+    /**
+     * Sets the class responsible for converting the collection into the list of currently-visible
+     * notifications.
+     */
+    public void setListBuilder(NotifListBuilder listBuilder) {
+        Assert.isMainThread();
+        mListBuilder = listBuilder;
+    }
+
+    /**
+     * Returns the list of "active" notifications, i.e. the notifications that are currently posted
+     * to the phone. In general, this tracks closely to the list maintained by NotificationManager,
+     * but it can diverge slightly due to lifetime extenders.
+     *
+     * The returned list is read-only, unsorted, unfiltered, and ungrouped.
+     */
+    public Collection<NotificationEntry> getNotifs() {
+        Assert.isMainThread();
+        return mReadOnlyNotificationSet;
+    }
+
+    /**
+     * Registers a listener to be informed when notifications are added, removed or updated.
+     */
+    public void addCollectionListener(NotifCollectionListener listener) {
+        Assert.isMainThread();
+        mNotifCollectionListeners.add(listener);
+    }
+
+    /**
+     * Registers a lifetime extender. Lifetime extenders can cause notifications that have been
+     * dismissed or retracted to be temporarily retained in the collection.
+     */
+    public void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
+        Assert.isMainThread();
+        checkForReentrantCall();
+        if (mLifetimeExtenders.contains(extender)) {
+            throw new IllegalArgumentException("Extender " + extender + " already added.");
+        }
+        mLifetimeExtenders.add(extender);
+        extender.setCallback(this::onEndLifetimeExtension);
+    }
+
+    /**
+     * Dismiss a notification on behalf of the user.
+     */
+    public void dismissNotification(
+            NotificationEntry entry,
+            @CancellationReason int reason,
+            @NonNull DismissedByUserStats stats) {
+        Assert.isMainThread();
+        checkNotNull(stats);
+        checkForReentrantCall();
+
+        removeNotification(entry.getKey(), null, reason, stats);
+    }
+
+    private void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+        Assert.isMainThread();
+
+        NotificationEntry entry = mNotificationSet.get(sbn.getKey());
+
+        if (entry == null) {
+            // A new notification!
+            Log.d(TAG, "POSTED  " + sbn.getKey());
+
+            entry = new NotificationEntry(sbn, requireRanking(rankingMap, sbn.getKey()));
+            mNotificationSet.put(sbn.getKey(), entry);
+            applyRanking(rankingMap);
+
+            dispatchOnEntryAdded(entry);
+
+        } else {
+            // Update to an existing entry
+            Log.d(TAG, "UPDATED " + sbn.getKey());
+
+            // Notification is updated so it is essentially re-added and thus alive again.  Don't
+            // need to keep its lifetime extended.
+            cancelLifetimeExtension(entry);
+
+            entry.setSbn(sbn);
+            applyRanking(rankingMap);
+
+            dispatchOnEntryUpdated(entry);
+        }
+
+        rebuildList();
+    }
+
+    private void onNotificationRemoved(
+            StatusBarNotification sbn,
+            @Nullable RankingMap rankingMap,
+            int reason) {
+        Assert.isMainThread();
+        Log.d(TAG, "REMOVED " + sbn.getKey() + " reason=" + reason);
+        removeNotification(sbn.getKey(), rankingMap, reason, null);
+    }
+
+    private void onNotificationRankingUpdate(RankingMap rankingMap) {
+        Assert.isMainThread();
+        applyRanking(rankingMap);
+        rebuildList();
+    }
+
+    private void removeNotification(
+            String key,
+            @Nullable RankingMap rankingMap,
+            @CancellationReason int reason,
+            DismissedByUserStats dismissedByUserStats) {
+
+        NotificationEntry entry = mNotificationSet.get(key);
+        if (entry == null) {
+            throw new IllegalStateException("No notification to remove with key " + key);
+        }
+
+        entry.mLifetimeExtenders.clear();
+        mAmDispatchingToOtherCode = true;
+        for (NotifLifetimeExtender extender : mLifetimeExtenders) {
+            if (extender.shouldExtendLifetime(entry, reason)) {
+                entry.mLifetimeExtenders.add(extender);
+            }
+        }
+        mAmDispatchingToOtherCode = false;
+
+        if (!isLifetimeExtended(entry)) {
+            mNotificationSet.remove(entry.getKey());
+
+            if (dismissedByUserStats != null) {
+                try {
+                    mStatusBarService.onNotificationClear(
+                            entry.getSbn().getPackageName(),
+                            entry.getSbn().getTag(),
+                            entry.getSbn().getId(),
+                            entry.getSbn().getUser().getIdentifier(),
+                            entry.getSbn().getKey(),
+                            dismissedByUserStats.dismissalSurface,
+                            dismissedByUserStats.dismissalSentiment,
+                            dismissedByUserStats.notificationVisibility);
+                } catch (RemoteException e) {
+                    // system process is dead if we're here.
+                }
+            }
+
+            if (rankingMap != null) {
+                applyRanking(rankingMap);
+            }
+
+            dispatchOnEntryRemoved(entry, reason, dismissedByUserStats != null /* removedByUser */);
+        }
+
+        rebuildList();
+    }
+
+    private void applyRanking(RankingMap rankingMap) {
+        for (NotificationEntry entry : mNotificationSet.values()) {
+            if (!isLifetimeExtended(entry)) {
+                Ranking ranking = requireRanking(rankingMap, entry.getKey());
+                entry.setRanking(ranking);
+            }
+        }
+    }
+
+    private void rebuildList() {
+        if (mListBuilder != null) {
+            mListBuilder.onBuildList(mReadOnlyNotificationSet);
+        }
+    }
+
+    private void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry) {
+        Assert.isMainThread();
+        if (!mAttached) {
+            return;
+        }
+        checkForReentrantCall();
+
+        if (!entry.mLifetimeExtenders.remove(extender)) {
+            throw new IllegalStateException(
+                    String.format(
+                            "Cannot end lifetime extension for extender \"%s\" (%s)",
+                            extender.getName(),
+                            extender));
+        }
+
+        if (!isLifetimeExtended(entry)) {
+            // TODO: This doesn't need to be undefined -- we can set either EXTENDER_EXPIRED or
+            // save the original reason
+            removeNotification(entry.getKey(), null, REASON_UNKNOWN, null);
+        }
+    }
+
+    private void cancelLifetimeExtension(NotificationEntry entry) {
+        mAmDispatchingToOtherCode = true;
+        for (NotifLifetimeExtender extender : entry.mLifetimeExtenders) {
+            extender.cancelLifetimeExtension(entry);
+        }
+        mAmDispatchingToOtherCode = false;
+        entry.mLifetimeExtenders.clear();
+    }
+
+    private boolean isLifetimeExtended(NotificationEntry entry) {
+        return entry.mLifetimeExtenders.size() > 0;
+    }
+
+    private void checkForReentrantCall() {
+        if (mAmDispatchingToOtherCode) {
+            throw new IllegalStateException("Reentrant call detected");
+        }
+    }
+
+    private static Ranking requireRanking(RankingMap rankingMap, String key) {
+        // TODO: Modify RankingMap so that we don't have to make a copy here
+        Ranking ranking = new Ranking();
+        if (!rankingMap.getRanking(key, ranking)) {
+            throw new IllegalArgumentException("Ranking map doesn't contain key: " + key);
+        }
+        return ranking;
+    }
+
+    private void dispatchOnEntryAdded(NotificationEntry entry) {
+        mAmDispatchingToOtherCode = true;
+        if (mListBuilder != null) {
+            mListBuilder.onBeginDispatchToListeners();
+        }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onEntryAdded(entry);
+        }
+        mAmDispatchingToOtherCode = false;
+    }
+
+    private void dispatchOnEntryUpdated(NotificationEntry entry) {
+        mAmDispatchingToOtherCode = true;
+        if (mListBuilder != null) {
+            mListBuilder.onBeginDispatchToListeners();
+        }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onEntryUpdated(entry);
+        }
+        mAmDispatchingToOtherCode = false;
+    }
+
+    private void dispatchOnEntryRemoved(
+            NotificationEntry entry,
+            @CancellationReason int reason,
+            boolean removedByUser) {
+        mAmDispatchingToOtherCode = true;
+        if (mListBuilder != null) {
+            mListBuilder.onBeginDispatchToListeners();
+        }
+        for (NotifCollectionListener listener : mNotifCollectionListeners) {
+            listener.onEntryRemoved(entry, reason, removedByUser);
+        }
+        mAmDispatchingToOtherCode = false;
+    }
+
+    private final NotifServiceListener mNotifServiceListener = new NotifServiceListener() {
+        @Override
+        public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+            NotifCollection.this.onNotificationPosted(sbn, rankingMap);
+        }
+
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+            NotifCollection.this.onNotificationRemoved(sbn, rankingMap, REASON_UNKNOWN);
+        }
+
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+                int reason) {
+            NotifCollection.this.onNotificationRemoved(sbn, rankingMap, reason);
+        }
+
+        @Override
+        public void onNotificationRankingUpdate(RankingMap rankingMap) {
+            NotifCollection.this.onNotificationRankingUpdate(rankingMap);
+        }
+    };
+
+    private static final String TAG = "NotifCollection";
+
+    @IntDef(prefix = { "REASON_" }, value = {
+            REASON_UNKNOWN,
+            REASON_CLICK,
+            REASON_CANCEL_ALL,
+            REASON_ERROR,
+            REASON_PACKAGE_CHANGED,
+            REASON_USER_STOPPED,
+            REASON_PACKAGE_BANNED,
+            REASON_APP_CANCEL,
+            REASON_APP_CANCEL_ALL,
+            REASON_LISTENER_CANCEL,
+            REASON_LISTENER_CANCEL_ALL,
+            REASON_GROUP_SUMMARY_CANCELED,
+            REASON_GROUP_OPTIMIZATION,
+            REASON_PACKAGE_SUSPENDED,
+            REASON_PROFILE_TURNED_OFF,
+            REASON_UNAUTOBUNDLED,
+            REASON_CHANNEL_BANNED,
+            REASON_SNOOZED,
+            REASON_TIMEOUT,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface CancellationReason {}
+
+    public static final int REASON_UNKNOWN = 0;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
new file mode 100644
index 0000000..032620e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
@@ -0,0 +1,46 @@
+/*
+ * 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.systemui.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+
+/**
+ * Listener interface for {@link NotifCollection}.
+ */
+public interface NotifCollectionListener {
+    /**
+     * Called whenever a notification with a new key is posted.
+     */
+    default void onEntryAdded(NotificationEntry entry) {
+    }
+
+    /**
+     * Called whenever a notification with the same key as an existing notification is posted. By
+     * the time this listener is called, the entry's SBN and Ranking will already have been updated.
+     */
+    default void onEntryUpdated(NotificationEntry entry) {
+    }
+
+    /**
+     * Called immediately after a notification has been removed from the collection.
+     */
+    default void onEntryRemoved(
+            NotificationEntry entry,
+            @CancellationReason int reason,
+            boolean removedByUser) {
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
new file mode 100644
index 0000000..2c7b138
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
@@ -0,0 +1,58 @@
+/*
+ * 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.systemui.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+
+/**
+ * A way for other code to temporarily extend the lifetime of a notification after it has been
+ * retracted. See {@link NotifCollection#addNotificationLifetimeExtender(NotifLifetimeExtender)}.
+ */
+public interface NotifLifetimeExtender {
+    /** Name to associate with this extender (for the purposes of debugging) */
+    String getName();
+
+    /**
+     * Called on the extender immediately after it has been registered. The extender should hang on
+     * to this callback and execute it whenever it no longer needs to extend the lifetime of a
+     * notification.
+     */
+    void setCallback(OnEndLifetimeExtensionCallback callback);
+
+    /**
+     * Called by the NotifCollection whenever a notification has been retracted (by the app) or
+     * dismissed (by the user). If the extender returns true, it is considered to be extending the
+     * lifetime of that notification. Lifetime-extended notifications are kept around until all
+     * active extenders expire their extension by calling onEndLifetimeExtension(). This method is
+     * called on all lifetime extenders even if earlier ones return true (in other words, multiple
+     * lifetime extenders can be extending a notification at the same time).
+     */
+    boolean shouldExtendLifetime(NotificationEntry entry, @CancellationReason int reason);
+
+    /**
+     * Called by the NotifCollection to inform a lifetime extender that its extension of a notif
+     * is no longer valid (usually because the notif has been reposted and so no longer needs
+     * lifetime extension). The extender should clean up any references it has to the notif in
+     * question.
+     */
+    void cancelLifetimeExtension(NotificationEntry entry);
+
+    /** Callback for notifying the NotifCollection that a lifetime extension has expired. */
+    interface OnEndLifetimeExtensionCallback {
+        void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java
new file mode 100644
index 0000000..17fef68
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * 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.systemui.statusbar.notification.collection;
+
+import java.util.Collection;
+
+/**
+ * Interface for the class responsible for converting a NotifCollection into the final sorted,
+ * filtered, and grouped list of currently visible notifications.
+ */
+public interface NotifListBuilder {
+    /**
+     * Called after the NotifCollection has received an update from NotificationManager but before
+     * it dispatches any change events to its listeners. This is to inform the list builder that
+     * the first stage of the pipeline has been triggered. After events have been dispatched,
+     * onBuildList() will be called.
+     *
+     * While onBuildList() is always called after this method is called, the converse is not always
+     * true: sometimes the NotifCollection applies an update that does not need to dispatch events,
+     * in which case this method will be skipped and onBuildList will be called directly.
+     */
+    void onBeginDispatchToListeners();
+
+    /**
+     * Called by the NotifCollection to indicate that something in the collection has changed and
+     * that the list builder should regenerate the list.
+     */
+    void onBuildList(Collection<NotificationEntry> entries);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index a98fa66..9981c93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -37,6 +37,7 @@
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.logging.NotifEvent;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
@@ -76,12 +77,16 @@
     private final Ranking mTmpRanking = new Ranking();
     private final boolean mUsePeopleFiltering;
     private final NotifLog mNotifLog;
+    private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
 
     @Inject
-    public NotificationData(NotificationSectionsFeatureManager sectionsFeatureManager,
-            NotifLog notifLog) {
+    public NotificationData(
+            NotificationSectionsFeatureManager sectionsFeatureManager,
+            NotifLog notifLog,
+            PeopleNotificationIdentifier peopleNotificationIdentifier) {
         mUsePeopleFiltering = sectionsFeatureManager.isFilteringEnabled();
         mNotifLog = notifLog;
+        mPeopleNotificationIdentifier = peopleNotificationIdentifier;
     }
 
     public void setHeadsUpManager(HeadsUpManager headsUpManager) {
@@ -93,10 +98,13 @@
             new Comparator<NotificationEntry>() {
         @Override
         public int compare(NotificationEntry a, NotificationEntry b) {
-            final StatusBarNotification na = a.notification;
-            final StatusBarNotification nb = b.notification;
-            int aRank = getRank(a.key);
-            int bRank = getRank(b.key);
+            final StatusBarNotification na = a.getSbn();
+            final StatusBarNotification nb = b.getSbn();
+            int aRank = getRank(a.getKey());
+            int bRank = getRank(b.getKey());
+
+            boolean aPeople = isPeopleNotification(a);
+            boolean bPeople = isPeopleNotification(b);
 
             boolean aMedia = isImportantMedia(a);
             boolean bMedia = isImportantMedia(b);
@@ -107,8 +115,8 @@
             boolean aHeadsUp = a.isRowHeadsUp();
             boolean bHeadsUp = b.isRowHeadsUp();
 
-            if (mUsePeopleFiltering && a.hasAssociatedPeople() != b.hasAssociatedPeople()) {
-                return a.hasAssociatedPeople() ? -1 : 1;
+            if (mUsePeopleFiltering && aPeople != bPeople) {
+                return aPeople ? -1 : 1;
             } else if (aHeadsUp != bHeadsUp) {
                 return aHeadsUp ? -1 : 1;
             } else if (aHeadsUp) {
@@ -164,7 +172,7 @@
             final int len = mEntries.size();
             for (int i = 0; i < len; i++) {
                 NotificationEntry entry = mEntries.valueAt(i);
-                final StatusBarNotification sbn = entry.notification;
+                final StatusBarNotification sbn = entry.getSbn();
                 if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
                     continue;
                 }
@@ -180,11 +188,11 @@
 
     public void add(NotificationEntry entry) {
         synchronized (mEntries) {
-            mEntries.put(entry.notification.getKey(), entry);
+            mEntries.put(entry.getSbn().getKey(), entry);
         }
         mGroupManager.onEntryAdded(entry);
 
-        updateRankingAndSort(mRankingMap, "addEntry=" + entry.sbn());
+        updateRankingAndSort(mRankingMap, "addEntry=" + entry.getSbn());
     }
 
     public NotificationEntry remove(String key, RankingMap ranking) {
@@ -194,7 +202,7 @@
         }
         if (removed == null) return null;
         mGroupManager.onEntryRemoved(removed);
-        updateRankingAndSort(ranking, "removeEntry=" + removed.sbn());
+        updateRankingAndSort(ranking, "removeEntry=" + removed.getSbn());
         return removed;
     }
 
@@ -205,8 +213,8 @@
             StatusBarNotification notification,
             String reason) {
         updateRanking(ranking, reason);
-        final StatusBarNotification oldNotification = entry.notification;
-        entry.setNotification(notification);
+        final StatusBarNotification oldNotification = entry.getSbn();
+        entry.setSbn(notification);
         mGroupManager.onEntryUpdated(entry, oldNotification);
     }
 
@@ -217,24 +225,6 @@
         updateRankingAndSort(ranking, reason);
     }
 
-    public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
-        synchronized (mEntries) {
-            final int len = mEntries.size();
-            for (int i = 0; i < len; i++) {
-                NotificationEntry entry = mEntries.valueAt(i);
-                if (uid == entry.notification.getUid()
-                        && pkg.equals(entry.notification.getPackageName())
-                        && key.equals(entry.key)) {
-                    if (showIcon) {
-                        entry.mActiveAppOps.add(appOp);
-                    } else {
-                        entry.mActiveAppOps.remove(appOp);
-                    }
-                }
-            }
-        }
-    }
-
     /**
      * Returns true if this notification should be displayed in the high-priority notifications
      * section
@@ -251,7 +241,7 @@
                 final ArrayList<NotificationEntry> logicalChildren =
                         mGroupManager.getLogicalChildren(statusBarNotification);
                 for (NotificationEntry child : logicalChildren) {
-                    if (isHighPriority(child.notification)) {
+                    if (isHighPriority(child.getSbn())) {
                         return true;
                     }
                 }
@@ -338,17 +328,17 @@
     }
 
     private boolean isImportantMedia(NotificationEntry e) {
-        int importance = e.ranking().getImportance();
-        boolean media = e.key.equals(getMediaManager().getMediaNotificationKey())
+        int importance = e.getRanking().getImportance();
+        boolean media = e.getKey().equals(getMediaManager().getMediaNotificationKey())
                 && importance > NotificationManager.IMPORTANCE_MIN;
 
         return media;
     }
 
     private boolean isSystemMax(NotificationEntry e) {
-        int importance = e.ranking().getImportance();
+        int importance = e.getRanking().getImportance();
         boolean sys = importance  >= NotificationManager.IMPORTANCE_HIGH
-                && isSystemNotification(e.notification);
+                && isSystemNotification(e.getSbn());
 
         return sys;
     }
@@ -369,18 +359,18 @@
                 for (int i = 0; i < len; i++) {
                     NotificationEntry entry = mEntries.valueAt(i);
                     Ranking newRanking = new Ranking();
-                    if (!getRanking(entry.key, newRanking)) {
+                    if (!getRanking(entry.getKey(), newRanking)) {
                         continue;
                     }
                     entry.setRanking(newRanking);
 
-                    final StatusBarNotification oldSbn = entry.notification.cloneLight();
+                    final StatusBarNotification oldSbn = entry.getSbn().cloneLight();
                     final String overrideGroupKey = newRanking.getOverrideGroupKey();
                     if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
-                        entry.notification.setOverrideGroupKey(overrideGroupKey);
+                        entry.getSbn().setOverrideGroupKey(overrideGroupKey);
                         mGroupManager.onEntryUpdated(entry, oldSbn);
                     }
-                    entry.setIsHighPriority(isHighPriority(entry.notification));
+                    entry.setIsHighPriority(isHighPriority(entry.getSbn()));
                 }
             }
         }
@@ -447,7 +437,7 @@
             boolean isHeadsUp,
             boolean isMedia,
             boolean isSystemMax) {
-        if (mUsePeopleFiltering && e.hasAssociatedPeople()) {
+        if (mUsePeopleFiltering && isPeopleNotification(e)) {
             e.setBucket(BUCKET_PEOPLE);
         } else if (isHeadsUp || isMedia || isSystemMax || e.isHighPriority()) {
             e.setBucket(BUCKET_ALERTING);
@@ -456,6 +446,10 @@
         }
     }
 
+    private boolean isPeopleNotification(NotificationEntry e) {
+        return mPeopleNotificationIdentifier.isPeopleNotification(e.getSbn());
+    }
+
     public void dump(PrintWriter pw, String indent) {
         int filteredLen = mSortedAndFiltered.size();
         pw.print(indent);
@@ -481,10 +475,10 @@
     }
 
     private void dumpEntry(PrintWriter pw, String indent, int i, NotificationEntry e) {
-        getRanking(e.key, mTmpRanking);
+        getRanking(e.getKey(), mTmpRanking);
         pw.print(indent);
-        pw.println("  [" + i + "] key=" + e.key + " icon=" + e.icon);
-        StatusBarNotification n = e.notification;
+        pw.println("  [" + i + "] key=" + e.getKey() + " icon=" + e.icon);
+        StatusBarNotification n = e.getSbn();
         pw.print(indent);
         pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " importance="
                 + mTmpRanking.getImportance());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index c3211e3..a4c8fc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -30,6 +30,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 
+import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
 
 import android.annotation.NonNull;
@@ -84,23 +85,30 @@
  * clean this up in the future.
  */
 public final class NotificationEntry {
-    private static final long LAUNCH_COOLDOWN = 2000;
-    private static final long REMOTE_INPUT_COOLDOWN = 500;
-    private static final long INITIALIZATION_DELAY = 400;
-    private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
-    private static final int COLOR_INVALID = 1;
 
-    public final String key;
-    public StatusBarNotification notification;
+    private final String mKey;
+    private StatusBarNotification mSbn;
     private Ranking mRanking;
 
-    public boolean noisy;
+
+    /*
+     * Bookkeeping members
+     */
+
+    /** List of lifetime extenders that are extending the lifetime of this notification. */
+    final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
+
+
+    /*
+    * Old members
+    * TODO: Remove every member beneath this line if possible
+    */
+
     public StatusBarIconView icon;
     public StatusBarIconView expandedIcon;
     public StatusBarIconView centeredIcon;
     public StatusBarIconView aodIcon;
     private boolean interruption;
-    public boolean autoRedacted; // whether the redacted notification was generated by us
     public int targetSdk;
     private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
     public CharSequence remoteInputText;
@@ -122,7 +130,7 @@
     private Throwable mDebugThrowable;
     public CharSequence remoteInputTextWhenReset;
     public long lastRemoteInputSent = NOT_LAUNCHED_YET;
-    public ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
+    public final ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
     public CharSequence headsUpStatusBarText;
     public CharSequence headsUpStatusBarTextPublic;
 
@@ -141,12 +149,6 @@
     private boolean hasSentReply;
 
     /**
-     * Whether this notification has changed in visual appearance since the previous post.
-     * New notifications are interruptive by default.
-     */
-    public boolean isVisuallyInterruptive;
-
-    /**
      * Whether this notification is shown to the user as a high priority notification: visible on
      * the lock screen/status bar and in the top section in the shade.
      */
@@ -161,34 +163,42 @@
     public NotificationEntry(
             @NonNull StatusBarNotification sbn,
             @NonNull Ranking ranking) {
-        this.key = sbn.getKey();
-        setNotification(sbn);
+        checkNotNull(sbn);
+        checkNotNull(sbn.getKey());
+        checkNotNull(ranking);
+
+        mKey = sbn.getKey();
+        setSbn(sbn);
         setRanking(ranking);
     }
 
     /** The key for this notification. Guaranteed to be immutable and unique */
-    public String key() {
-        return key;
+    public String getKey() {
+        return mKey;
     }
 
     /**
      * The StatusBarNotification that represents one half of a NotificationEntry (the other half
      * being the Ranking). This object is swapped out whenever a notification is updated.
      */
-    public StatusBarNotification sbn() {
-        return notification;
+    public StatusBarNotification getSbn() {
+        return mSbn;
     }
 
     /**
      * Should only be called by NotificationEntryManager and friends.
      * TODO: Make this package-private
      */
-    public void setNotification(StatusBarNotification sbn) {
-        if (sbn.getKey() != null && key != null && !sbn.getKey().equals(key)) {
+    public void setSbn(@NonNull StatusBarNotification sbn) {
+        checkNotNull(sbn);
+        checkNotNull(sbn.getKey());
+
+        if (!sbn.getKey().equals(mKey)) {
             throw new IllegalArgumentException("New key " + sbn.getKey()
-                    + " doesn't match existing key " + key);
+                    + " doesn't match existing key " + mKey);
         }
-        notification = sbn;
+
+        mSbn = sbn;
         updatePeopleList();
     }
 
@@ -197,7 +207,7 @@
      * StatusBarNotification). This object is swapped out whenever a the ranking is updated (which
      * generally occurs whenever anything changes in the notification list).
      */
-    public Ranking ranking() {
+    public Ranking getRanking() {
         return mRanking;
     }
 
@@ -206,14 +216,22 @@
      * TODO: Make this package-private
      */
     public void setRanking(@NonNull Ranking ranking) {
-        if (!ranking.getKey().equals(key)) {
+        checkNotNull(ranking);
+        checkNotNull(ranking.getKey());
+
+        if (!ranking.getKey().equals(mKey)) {
             throw new IllegalArgumentException("New key " + ranking.getKey()
-                    + " doesn't match existing key " + key);
+                    + " doesn't match existing key " + mKey);
         }
+
         mRanking = ranking;
-        isVisuallyInterruptive = ranking.visuallyInterruptive();
     }
 
+
+    /*
+     * Convenience getters for SBN and Ranking members
+     */
+
     public NotificationChannel getChannel() {
         return mRanking.getChannel();
     }
@@ -261,6 +279,12 @@
     }
 
 
+    /*
+     * Old methods
+     *
+     * TODO: Remove as many of these as possible
+     */
+
     public void setInterruption() {
         interruption = true;
     }
@@ -278,13 +302,13 @@
     }
 
     public boolean isBubble() {
-        return (notification.getNotification().flags & FLAG_BUBBLE) != 0;
+        return (mSbn.getNotification().flags & FLAG_BUBBLE) != 0;
     }
 
     private void updatePeopleList() {
         mAssociatedPeople.clear();
 
-        Bundle extras = notification.getNotification().extras;
+        Bundle extras = mSbn.getNotification().extras;
         if (extras == null) {
             return;
         }
@@ -296,7 +320,7 @@
         }
 
         if (Notification.MessagingStyle.class.equals(
-                notification.getNotification().getNotificationStyle())) {
+                mSbn.getNotification().getNotificationStyle())) {
             final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
             if (!ArrayUtils.isEmpty(messages)) {
                 for (Notification.MessagingStyle.Message message :
@@ -316,7 +340,7 @@
      * Returns the data needed for a bubble for this notification, if it exists.
      */
     public Notification.BubbleMetadata getBubbleMetadata() {
-        return notification.getNotification().getBubbleMetadata();
+        return mSbn.getNotification().getBubbleMetadata();
     }
 
     /**
@@ -438,7 +462,7 @@
                 });
 
         // Construct the centered icon
-        if (notification.getNotification().isMediaNotification()) {
+        if (mSbn.getNotification().isMediaNotification()) {
             centeredIcon = new StatusBarIconView(context,
                     sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
             centeredIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
@@ -478,8 +502,8 @@
             // Update the icon
             Notification n = sbn.getNotification();
             final StatusBarIcon ic = new StatusBarIcon(
-                    notification.getUser(),
-                    notification.getPackageName(),
+                    mSbn.getUser(),
+                    mSbn.getPackageName(),
                     n.getSmallIcon(),
                     n.iconLevel,
                     n.number,
@@ -503,7 +527,7 @@
     public int getContrastedColor(Context context, boolean isLowPriority,
             int backgroundColor) {
         int rawColor = isLowPriority ? Notification.COLOR_DEFAULT :
-                notification.getNotification().color;
+                mSbn.getNotification().color;
         if (mCachedContrastColorIsFor == rawColor && mCachedContrastColor != COLOR_INVALID) {
             return mCachedContrastColor;
         }
@@ -569,7 +593,7 @@
         if (!hasSentReply) {
             return false;
         }
-        Bundle extras = notification.getNotification().extras;
+        Bundle extras = mSbn.getNotification().extras;
         CharSequence[] replyTexts = extras.getCharSequenceArray(
                 Notification.EXTRA_REMOTE_INPUT_HISTORY);
         if (!ArrayUtils.isEmpty(replyTexts)) {
@@ -771,7 +795,7 @@
      * @see #canViewBeDismissed()
      */
     public boolean isClearable() {
-        if (notification == null || !notification.isClearable()) {
+        if (!mSbn.isClearable()) {
             return false;
         }
 
@@ -794,15 +818,15 @@
 
     @VisibleForTesting
     boolean isExemptFromDndVisualSuppression() {
-        if (isNotificationBlockedByPolicy(notification.getNotification())) {
+        if (isNotificationBlockedByPolicy(mSbn.getNotification())) {
             return false;
         }
 
-        if ((notification.getNotification().flags
+        if ((mSbn.getNotification().flags
                 & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
             return true;
         }
-        if (notification.getNotification().isMediaNotification()) {
+        if (mSbn.getNotification().isMediaNotification()) {
             return true;
         }
         if (mIsSystemNotification != null && mIsSystemNotification) {
@@ -935,4 +959,10 @@
             this.index = index;
         }
     }
+
+    private static final long LAUNCH_COOLDOWN = 2000;
+    private static final long REMOTE_INPUT_COOLDOWN = 500;
+    private static final long INITIALIZATION_DELAY = 400;
+    private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
+    private static final int COLOR_INVALID = 1;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index e5571b6..396c5fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -135,9 +135,9 @@
             throws InflationException {
         ViewGroup parent = mListContainer.getViewParentForNotification(entry);
         PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
-                entry.notification.getUser().getIdentifier());
+                entry.getSbn().getUser().getIdentifier());
 
-        final StatusBarNotification sbn = entry.notification;
+        final StatusBarNotification sbn = entry.getSbn();
         if (entry.rowExists()) {
             entry.updateIcons(mContext, sbn);
             entry.reset();
@@ -156,7 +156,7 @@
     private void bindRow(NotificationEntry entry, PackageManager pmUser,
             StatusBarNotification sbn, ExpandableNotificationRow row,
             Runnable onDismissRunnable) {
-        row.setExpansionLogger(mExpansionLogger, entry.notification.getKey());
+        row.setExpansionLogger(mExpansionLogger, entry.getSbn().getKey());
         row.setBypassController(mKeyguardBypassController);
         row.setStatusBarStateController(mStatusBarStateController);
         row.setGroupManager(mGroupManager);
@@ -213,8 +213,8 @@
                 entry.reset();
                 PackageManager pmUser = StatusBar.getPackageManagerForUser(
                         mContext,
-                        entry.notification.getUser().getIdentifier());
-                updateNotification(entry, pmUser, entry.notification, entry.getRow());
+                        entry.getSbn().getUser().getIdentifier());
+                updateNotification(entry, pmUser, entry.getSbn(), entry.getRow());
             } else {
                 // Once the RowInflaterTask is done, it will pick up the updated entry, so
                 // no-op here.
@@ -248,7 +248,6 @@
 
         // TODO: should updates to the entry be happening somewhere else?
         entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
-        entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
 
         entry.setRow(row);
         row.setOnActivatedListener(mPresenter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
index 7703cbd..8ebbca2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
@@ -27,12 +27,11 @@
 
 /**
  * An event related to notifications. {@link NotifLog} stores and prints these events for debugging
- * and triaging purposes.
+ * and triaging purposes. We do not store a copy of the status bar notification nor ranking
+ * here to mitigate memory usage.
  */
 public class NotifEvent extends RichEvent {
     public static final int TOTAL_EVENT_TYPES = 11;
-    private final StatusBarNotification mSbn;
-    private final Ranking mRanking;
 
     /**
      * Creates a NotifEvent with an event type that matches with an index in the array
@@ -44,34 +43,20 @@
     public NotifEvent(int logLevel, int type, String reason, StatusBarNotification sbn,
             Ranking ranking) {
         super(logLevel, type, reason);
+        mMessage += getExtraInfo(sbn, ranking);
+    }
+
+    private String getExtraInfo(StatusBarNotification sbn, Ranking ranking) {
+        StringBuilder extraInfo = new StringBuilder();
 
         if (sbn != null) {
-            mSbn = sbn.cloneLight();
-        } else {
-            mSbn = null;
+            extraInfo.append(" Sbn=");
+            extraInfo.append(sbn);
         }
 
         if (ranking != null) {
-            mRanking = new Ranking();
-            mRanking.populate(ranking);
-        } else {
-            mRanking = null;
-        }
-
-        mMessage += getExtraInfo();
-    }
-
-    private String getExtraInfo() {
-        StringBuilder extraInfo = new StringBuilder();
-
-        if (mSbn != null) {
-            extraInfo.append(" Sbn=");
-            extraInfo.append(mSbn);
-        }
-
-        if (mRanking != null) {
             extraInfo.append(" Ranking=");
-            extraInfo.append(mRanking);
+            extraInfo.append(ranking);
         }
 
         return extraInfo.toString();
@@ -107,13 +92,6 @@
     }
 
     /**
-     * @return a copy of the status bar notification that changed with this event
-     */
-    public StatusBarNotification getSbn() {
-        return mSbn;
-    }
-
-    /**
      * Builds a NotifEvent.
      */
     public static class NotifEventBuilder extends RichEvent.Builder<NotifEventBuilder> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
index 8466d2e8..1292831 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
@@ -111,7 +111,7 @@
      * @return true if successfully logged, else false
      */
     public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry) {
-        return log(eventType, entry.sbn(), entry.ranking(), "");
+        return log(eventType, entry.getSbn(), entry.getRanking(), "");
     }
 
     /**
@@ -120,6 +120,6 @@
      */
     public boolean log(@NotifEvent.EventType int eventType, NotificationEntry entry,
             String msg) {
-        return log(eventType, entry.sbn(), entry.ranking(), msg);
+        return log(eventType, entry.getSbn(), entry.getRanking(), msg);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 81275fd..b7f408e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -126,7 +126,7 @@
             int N = activeNotifications.size();
             for (int i = 0; i < N; i++) {
                 NotificationEntry entry = activeNotifications.get(i);
-                String key = entry.notification.getKey();
+                String key = entry.getSbn().getKey();
                 boolean isVisible = mListContainer.isInVisibleLocation(entry);
                 NotificationVisibility visObj = NotificationVisibility.obtain(key, i, N, isVisible,
                         getNotificationLocation(entry));
@@ -214,14 +214,14 @@
                     NotificationVisibility visibility,
                     boolean removedByUser) {
                 if (removedByUser && visibility != null) {
-                    logNotificationClear(entry.key, entry.notification, visibility);
+                    logNotificationClear(entry.getKey(), entry.getSbn(), visibility);
                 }
-                mExpansionStateLogger.onEntryRemoved(entry.key);
+                mExpansionStateLogger.onEntryRemoved(entry.getKey());
             }
 
             @Override
             public void onEntryReinflated(NotificationEntry entry) {
-                mExpansionStateLogger.onEntryReinflated(entry.key);
+                mExpansionStateLogger.onEntryReinflated(entry.getKey());
             }
 
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt
new file mode 100644
index 0000000..2c0c942
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.systemui.statusbar.notification.people
+
+import android.app.PendingIntent
+import android.graphics.drawable.Drawable
+
+/** `ViewModel` for PeopleHub view. */
+data class PeopleHubViewModel(val people: Sequence<PersonViewModel>, val isVisible: Boolean)
+
+/** `ViewModel` for a single "Person' in PeopleHub. */
+data class PersonViewModel(
+    val name: CharSequence,
+    val icon: Drawable,
+    val onClick: () -> Unit
+)
+
+/** `Model` for PeopleHub. */
+data class PeopleHubModel(val people: Collection<PersonModel>)
+
+/** `Model` for a single "Person" in PeopleHub. */
+data class PersonModel(
+    val key: PersonKey,
+    val name: CharSequence,
+    val avatar: Drawable,
+    val clickIntent: PendingIntent
+)
+
+/** Unique identifier for a Person in PeopleHub. */
+typealias PersonKey = String
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
new file mode 100644
index 0000000..4570989
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.systemui.statusbar.notification.people
+
+import dagger.Binds
+import dagger.Module
+
+@Module
+abstract class PeopleHubModule {
+
+    @Binds
+    abstract fun peopleHubSectionFooterViewController(
+        impl: PeopleHubSectionFooterViewAdapterImpl
+    ): PeopleHubSectionFooterViewAdapter
+
+    @Binds
+    abstract fun peopleHubDataSource(impl: PeopleHubDataSourceImpl): DataSource<PeopleHubModel>
+
+    @Binds
+    abstract fun peopleHubViewModelFactoryDataSource(
+        impl: PeopleHubViewModelFactoryDataSourceImpl
+    ): DataSource<PeopleHubViewModelFactory>
+
+    @Binds
+    abstract fun peopleNotificationIdentifier(
+        impl: PeopleNotificationIdentifierImpl
+    ): PeopleNotificationIdentifier
+
+    @Binds
+    abstract fun notificationPersonExtractor(
+        pluginImpl: NotificationPersonExtractorPluginBoundary
+    ): NotificationPersonExtractor
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
new file mode 100644
index 0000000..fe257d9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt
@@ -0,0 +1,272 @@
+/*
+ * 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.systemui.statusbar.notification.people
+
+import android.app.Notification
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.PixelFormat
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import android.service.notification.StatusBarNotification
+import android.util.TypedValue
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import com.android.internal.statusbar.NotificationVisibility
+import com.android.internal.widget.MessagingGroup
+import com.android.launcher3.icons.BaseIconFactory
+import com.android.systemui.R
+import com.android.systemui.plugins.NotificationPersonExtractorPlugin
+import com.android.systemui.statusbar.notification.NotificationEntryListener
+import com.android.systemui.statusbar.notification.NotificationEntryManager
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.policy.ExtensionController
+import java.util.ArrayDeque
+import javax.inject.Inject
+import javax.inject.Singleton
+
+private const val MAX_STORED_INACTIVE_PEOPLE = 10
+
+interface NotificationPersonExtractor {
+    fun extractPerson(sbn: StatusBarNotification): PersonModel?
+    fun extractPersonKey(sbn: StatusBarNotification): String?
+}
+
+@Singleton
+class NotificationPersonExtractorPluginBoundary @Inject constructor(
+    extensionController: ExtensionController,
+    private val context: Context
+) : NotificationPersonExtractor {
+
+    private var plugin: NotificationPersonExtractorPlugin? = null
+
+    init {
+        plugin = extensionController
+                .newExtension(NotificationPersonExtractorPlugin::class.java)
+                .withPlugin(NotificationPersonExtractorPlugin::class.java)
+                .withCallback { extractor ->
+                    plugin = extractor
+                }
+                .build()
+                .get()
+    }
+
+    override fun extractPerson(sbn: StatusBarNotification) =
+            plugin?.extractPerson(sbn)?.let { data ->
+                val badged = addBadgeToDrawable(data.avatar, context, sbn.packageName, sbn.user)
+                PersonModel(data.key, data.name, badged, data.clickIntent)
+            }
+
+    override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn)
+}
+
+@Singleton
+class PeopleHubDataSourceImpl @Inject constructor(
+    private val notificationEntryManager: NotificationEntryManager,
+    private val peopleHubManager: PeopleHubManager,
+    private val extractor: NotificationPersonExtractor
+) : DataSource<PeopleHubModel> {
+
+    private val dataListeners = mutableListOf<DataListener<PeopleHubModel>>()
+
+    private val notificationEntryListener = object : NotificationEntryListener {
+        override fun onEntryInflated(entry: NotificationEntry, inflatedFlags: Int) =
+                addVisibleEntry(entry)
+
+        override fun onEntryReinflated(entry: NotificationEntry) = addVisibleEntry(entry)
+
+        override fun onPostEntryUpdated(entry: NotificationEntry) = addVisibleEntry(entry)
+
+        override fun onEntryRemoved(
+            entry: NotificationEntry,
+            visibility: NotificationVisibility?,
+            removedByUser: Boolean
+        ) = removeVisibleEntry(entry)
+    }
+
+    private fun removeVisibleEntry(entry: NotificationEntry) {
+        val key = extractor.extractPersonKey(entry.sbn) ?: entry.extractPersonKey()
+        if (key?.let(peopleHubManager::removeActivePerson) == true) {
+            updateUi()
+        }
+    }
+
+    private fun addVisibleEntry(entry: NotificationEntry) {
+        val personModel = extractor.extractPerson(entry.sbn) ?: entry.extractPerson()
+        if (personModel?.let(peopleHubManager::addActivePerson) == true) {
+            updateUi()
+        }
+    }
+
+    override fun registerListener(listener: DataListener<PeopleHubModel>): Subscription {
+        val registerWithNotificationEntryManager = dataListeners.isEmpty()
+        dataListeners.add(listener)
+        if (registerWithNotificationEntryManager) {
+            notificationEntryManager.addNotificationEntryListener(notificationEntryListener)
+        } else {
+            listener.onDataChanged(peopleHubManager.getPeopleHubModel())
+        }
+        return object : Subscription {
+            override fun unsubscribe() {
+                dataListeners.remove(listener)
+                if (dataListeners.isEmpty()) {
+                    notificationEntryManager
+                            .removeNotificationEntryListener(notificationEntryListener)
+                }
+            }
+        }
+    }
+
+    private fun updateUi() {
+        val model = peopleHubManager.getPeopleHubModel()
+        for (listener in dataListeners) {
+            listener.onDataChanged(model)
+        }
+    }
+}
+
+@Singleton
+class PeopleHubManager @Inject constructor() {
+
+    private val activePeople = mutableMapOf<PersonKey, PersonModel>()
+    private val inactivePeople = ArrayDeque<PersonModel>(MAX_STORED_INACTIVE_PEOPLE)
+
+    fun removeActivePerson(key: PersonKey): Boolean {
+        activePeople.remove(key)?.let { data ->
+            if (inactivePeople.size >= MAX_STORED_INACTIVE_PEOPLE) {
+                inactivePeople.removeLast()
+            }
+            inactivePeople.push(data)
+            return true
+        }
+        return false
+    }
+
+    fun addActivePerson(person: PersonModel): Boolean {
+        activePeople[person.key] = person
+        return inactivePeople.removeIf { it.key == person.key }
+    }
+
+    fun getPeopleHubModel(): PeopleHubModel = PeopleHubModel(inactivePeople)
+}
+
+private val ViewGroup.children
+    get(): Sequence<View> = sequence {
+        for (i in 0 until childCount) {
+            yield(getChildAt(i))
+        }
+    }
+
+private fun ViewGroup.childrenWithId(id: Int): Sequence<View> = children.filter { it.id == id }
+
+private fun NotificationEntry.extractPerson(): PersonModel? {
+    if (!isMessagingNotification()) {
+        return null
+    }
+    val clickIntent = sbn.notification.contentIntent
+            ?: return null
+    val extras = sbn.notification.extras
+    val name = extras.getString(Notification.EXTRA_CONVERSATION_TITLE)
+            ?: extras.getString(Notification.EXTRA_TITLE)
+            ?: return null
+    val drawable = extractAvatarFromRow(this) ?: return null
+    val badgedAvatar = addBadgeToDrawable(drawable, row.context, sbn.packageName, sbn.user)
+    return PersonModel(key, name, badgedAvatar, clickIntent)
+}
+
+private fun addBadgeToDrawable(
+    drawable: Drawable,
+    context: Context,
+    packageName: String,
+    user: UserHandle
+): Drawable {
+    val pm = context.packageManager
+    val appInfo = pm.getApplicationInfoAsUser(packageName, 0, user)
+    return object : Drawable() {
+        override fun draw(canvas: Canvas) {
+            val iconBounds = getBounds()
+            val factory = object : BaseIconFactory(
+                    context,
+                    0 /* unused */,
+                    iconBounds.width(),
+                    true) {}
+            val badge = factory.createBadgedIconBitmap(
+                    appInfo.loadIcon(pm),
+                    user,
+                    true,
+                    appInfo.isInstantApp,
+                    null)
+            val badgeDrawable = BitmapDrawable(context.resources, badge.icon)
+                    .apply {
+                        alpha = drawable.alpha
+                        colorFilter = drawable.colorFilter
+                        val badgeWidth = TypedValue.applyDimension(
+                                TypedValue.COMPLEX_UNIT_DIP,
+                                15f,
+                                context.resources.displayMetrics
+                        ).toInt()
+                        setBounds(
+                                iconBounds.left + (iconBounds.width() - badgeWidth),
+                                iconBounds.top + (iconBounds.height() - badgeWidth),
+                                iconBounds.right,
+                                iconBounds.bottom)
+                    }
+            drawable.bounds = iconBounds
+            drawable.draw(canvas)
+            badgeDrawable.draw(canvas)
+        }
+
+        override fun setAlpha(alpha: Int) {
+            drawable.alpha = alpha
+        }
+
+        override fun setColorFilter(colorFilter: ColorFilter?) {
+            drawable.colorFilter = colorFilter
+        }
+
+        @PixelFormat.Opacity
+        override fun getOpacity(): Int = PixelFormat.OPAQUE
+    }
+}
+
+private fun extractAvatarFromRow(entry: NotificationEntry): Drawable? =
+        entry.row
+                ?.childrenWithId(R.id.expanded)
+                ?.mapNotNull { it as? ViewGroup }
+                ?.flatMap {
+                    it.childrenWithId(com.android.internal.R.id.status_bar_latest_event_content)
+                }
+                ?.mapNotNull {
+                    it.findViewById<ViewGroup>(com.android.internal.R.id.notification_messaging)
+                }
+                ?.mapNotNull { messagesView ->
+                    messagesView.children
+                            .mapNotNull { it as? MessagingGroup }
+                            .lastOrNull()
+                            ?.findViewById<ImageView>(com.android.internal.R.id.message_icon)
+                            ?.drawable
+                }
+                ?.firstOrNull()
+
+private fun NotificationEntry.extractPersonKey(): PersonKey? =
+        if (isMessagingNotification()) key else null
+
+private fun NotificationEntry.isMessagingNotification() =
+        sbn.notification.notificationStyle == Notification.MessagingStyle::class.java
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
new file mode 100644
index 0000000..5c35408
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
@@ -0,0 +1,133 @@
+/*
+ * 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.systemui.statusbar.notification.people
+
+import android.view.View
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/** Boundary between the View and PeopleHub, as seen by the View. */
+interface PeopleHubSectionFooterViewAdapter {
+    fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary)
+}
+
+/** Abstract `View` representation of PeopleHub footer in [NotificationSectionsManager]. */
+interface PeopleHubSectionFooterViewBoundary {
+    /** View used for animating the activity launch caused by clicking a person in the hub. */
+    val associatedViewForClickAnimation: View
+
+    /** [DataListener]s for individual people in the hub. */
+    val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
+
+    /** Sets the visibility of the Hub in the notification shade. */
+    fun setVisible(isVisible: Boolean)
+}
+
+/** Creates a [PeopleHubViewModel] given some additional information required from the `View`. */
+interface PeopleHubViewModelFactory {
+
+    /**
+     * Creates a [PeopleHubViewModel] that, when clicked, starts an activity using an animation
+     * involving the given [view].
+     */
+    fun createWithAssociatedClickView(view: View): PeopleHubViewModel
+}
+
+/**
+ * Wraps a [PeopleHubSectionFooterViewBoundary] in a [DataListener], and connects it to the data
+ * pipeline.
+ *
+ * @param dataSource PeopleHub data pipeline.
+ */
+@Singleton
+class PeopleHubSectionFooterViewAdapterImpl @Inject constructor(
+    private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubViewModelFactory>
+) : PeopleHubSectionFooterViewAdapter {
+
+    override fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary) {
+        dataSource.registerListener(PeopleHubDataListenerImpl(viewBoundary))
+    }
+}
+
+private class PeopleHubDataListenerImpl(
+    private val viewBoundary: PeopleHubSectionFooterViewBoundary
+) : DataListener<PeopleHubViewModelFactory> {
+
+    override fun onDataChanged(data: PeopleHubViewModelFactory) {
+        val viewModel = data.createWithAssociatedClickView(
+                viewBoundary.associatedViewForClickAnimation
+        )
+        viewBoundary.setVisible(viewModel.isVisible)
+        val padded = viewModel.people + repeated(null)
+        for ((personAdapter, personModel) in viewBoundary.personViewAdapters.zip(padded)) {
+            personAdapter.onDataChanged(personModel)
+        }
+    }
+}
+
+/**
+ * Converts [PeopleHubModel]s into [PeopleHubViewModelFactory]s.
+ *
+ * This class serves as the glue between the View layer (which depends on
+ * [PeopleHubSectionFooterViewBoundary]) and the Data layer (which produces [PeopleHubModel]s).
+ */
+@Singleton
+class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor(
+    private val activityStarter: ActivityStarter,
+    private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel>
+) : DataSource<PeopleHubViewModelFactory> {
+
+    override fun registerListener(listener: DataListener<PeopleHubViewModelFactory>) =
+            dataSource.registerListener(PeopleHubModelListenerImpl(activityStarter, listener))
+}
+
+private class PeopleHubModelListenerImpl(
+    private val activityStarter: ActivityStarter,
+    private val dataListener: DataListener<PeopleHubViewModelFactory>
+) : DataListener<PeopleHubModel> {
+
+    override fun onDataChanged(data: PeopleHubModel) =
+            dataListener.onDataChanged(PeopleHubViewModelFactoryImpl(data, activityStarter))
+}
+
+private class PeopleHubViewModelFactoryImpl(
+    private val data: PeopleHubModel,
+    private val activityStarter: ActivityStarter
+) : PeopleHubViewModelFactory {
+
+    override fun createWithAssociatedClickView(view: View): PeopleHubViewModel {
+        val personViewModels = data.people.asSequence().map { personModel ->
+            val onClick = {
+                activityStarter.startPendingIntentDismissingKeyguard(
+                        personModel.clickIntent,
+                        null,
+                        view
+                )
+            }
+            PersonViewModel(personModel.name, personModel.avatar, onClick)
+        }
+        return PeopleHubViewModel(personViewModels, data.people.isNotEmpty())
+    }
+}
+
+private fun <T> repeated(value: T): Sequence<T> = sequence {
+    while (true) {
+        yield(value)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
new file mode 100644
index 0000000..bfd4070
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.systemui.statusbar.notification.people
+
+import android.app.Notification
+import android.service.notification.StatusBarNotification
+import javax.inject.Inject
+import javax.inject.Singleton
+
+interface PeopleNotificationIdentifier {
+    fun isPeopleNotification(sbn: StatusBarNotification): Boolean
+}
+
+@Singleton
+class PeopleNotificationIdentifierImpl @Inject constructor(
+    private val personExtractor: NotificationPersonExtractor
+) : PeopleNotificationIdentifier {
+
+    override fun isPeopleNotification(sbn: StatusBarNotification) =
+            sbn.notification.notificationStyle == Notification.MessagingStyle::class.java ||
+                    personExtractor.extractPersonKey(sbn) != null
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
new file mode 100644
index 0000000..3ca3792
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.systemui.statusbar.notification.people
+
+/** Boundary between a View and data pipeline, as seen by the pipeline. */
+interface DataListener<in T> {
+    fun onDataChanged(data: T)
+}
+
+/** Convert all data using the given [mapper] before invoking this [DataListener]. */
+fun <S, T> DataListener<T>.contraMap(mapper: (S) -> T): DataListener<S> = object : DataListener<S> {
+    override fun onDataChanged(data: S) = onDataChanged(mapper(data))
+}
+
+/** Boundary between a View and data pipeline, as seen by the View. */
+interface DataSource<out T> {
+    fun registerListener(listener: DataListener<T>): Subscription
+}
+
+/** Represents a registration with a [DataSource]. */
+interface Subscription {
+    /** Removes the previously registered [DataListener] from the [DataSource] */
+    fun unsubscribe()
+}
+
+/** Transform all data coming out of this [DataSource] using the given [mapper]. */
+fun <S, T> DataSource<S>.map(mapper: (S) -> T): DataSource<T> = object : DataSource<T> {
+    override fun registerListener(listener: DataListener<T>) =
+            registerListener(listener.contraMap(mapper))
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 924a347..536db67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -442,7 +442,7 @@
      */
     public void setEntry(@NonNull NotificationEntry entry) {
         mEntry = entry;
-        mStatusBarNotification = entry.notification;
+        mStatusBarNotification = entry.getSbn();
         cacheIsSystemNotification();
     }
 
@@ -1203,7 +1203,7 @@
         // Let's update our childrencontainer. This is intentionally not guarded with
         // mIsSummaryWithChildren since we might have had children but not anymore.
         if (mChildrenContainer != null) {
-            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
+            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.getSbn());
         }
         if (mGuts != null) {
             NotificationGuts oldGuts = mGuts;
@@ -2303,7 +2303,7 @@
 
     private void updateRippleAllowed() {
         boolean allowed = isOnKeyguard()
-                || mEntry.notification.getNotification().contentIntent == null;
+                || mEntry.getSbn().getNotification().contentIntent == null;
         setRippleAllowed(allowed);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index a612a17..a91a119 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -230,7 +230,7 @@
         }
         // Only inflate the ones that are set.
         reInflateFlags &= mInflationFlags;
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
 
         // To check if the notification has inline image and preload inline image if necessary.
         mRow.getImageResolver().preloadImages(sbn.getNotification());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index f30a8b1..b12c76c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1097,7 +1097,7 @@
     }
 
     public void onNotificationUpdated(NotificationEntry entry) {
-        mStatusBarNotification = entry.notification;
+        mStatusBarNotification = entry.getSbn();
         mOnContentViewInactiveListeners.clear();
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateAllSingleLineViews();
@@ -1179,7 +1179,7 @@
                 : mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions();
         if (DEBUG) {
             Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.",
-                    entry.notification.getKey(),
+                    entry.getSbn().getKey(),
                     mCurrentSmartRepliesAndActions.smartActions == null ? 0 :
                             mCurrentSmartRepliesAndActions.smartActions.actions.size(),
                     mCurrentSmartRepliesAndActions.smartReplies == null ? 0 :
@@ -1253,7 +1253,7 @@
                 }
             }
             if (hasRemoteInput) {
-                int color = entry.notification.getNotification().color;
+                int color = entry.getSbn().getNotification().color;
                 if (color == Notification.COLOR_DEFAULT) {
                     color = mContext.getColor(R.color.default_remote_input_background);
                 }
@@ -1267,7 +1267,7 @@
                 if (existingPendingIntent != null || existing.isActive()) {
                     // The current action could be gone, or the pending intent no longer valid.
                     // If we find a matching action in the new notification, focus, otherwise close.
-                    Notification.Action[] actions = entry.notification.getNotification().actions;
+                    Notification.Action[] actions = entry.getSbn().getNotification().actions;
                     if (existingPendingIntent != null) {
                         existing.setPendingIntent(existingPendingIntent);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 2b7deec..1de2cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -494,15 +494,17 @@
     @Override
     public void setShouldManageLifetime(NotificationEntry entry, boolean shouldExtend) {
         if (shouldExtend) {
-            mKeyToRemoveOnGutsClosed = entry.key;
+            mKeyToRemoveOnGutsClosed = entry.getKey();
             if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "Keeping notification because it's showing guts. " + entry.key);
+                Log.d(TAG, "Keeping notification because it's showing guts. " + entry.getKey());
             }
         } else {
-            if (mKeyToRemoveOnGutsClosed != null && mKeyToRemoveOnGutsClosed.equals(entry.key)) {
+            if (mKeyToRemoveOnGutsClosed != null
+                    && mKeyToRemoveOnGutsClosed.equals(entry.getKey())) {
                 mKeyToRemoveOnGutsClosed = null;
                 if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Notification that was kept for guts was updated. " + entry.key);
+                    Log.d(TAG, "Notification that was kept for guts was updated. "
+                            + entry.getKey());
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 1116106..9bc0ca4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -28,6 +28,7 @@
 import android.media.session.PlaybackState;
 import android.metrics.LogMaker;
 import android.os.Handler;
+import android.provider.Settings;
 import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -41,9 +42,12 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.widget.MediaNotificationView;
 import com.android.systemui.Dependency;
+import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QuickQSPanel;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 
 import java.util.Timer;
 import java.util.TimerTask;
@@ -175,9 +179,29 @@
         mActions = mView.findViewById(com.android.internal.R.id.media_actions);
         mIsViewVisible = mView.isShown();
 
-        final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras
+        final MediaSession.Token token = mRow.getEntry().getSbn().getNotification().extras
                 .getParcelable(Notification.EXTRA_MEDIA_SESSION);
 
+        int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
+        if (flag == 1) {
+            StatusBarWindowController ctrl = Dependency.get(StatusBarWindowController.class);
+            QuickQSPanel panel = ctrl.getStatusBarView().findViewById(
+                    com.android.systemui.R.id.quick_qs_panel);
+            panel.getMediaPlayer().setMediaSession(token,
+                    mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+                    getNotificationHeader().getOriginalIconColor(),
+                    mRow.getCurrentBackgroundTint(),
+                    mActions);
+            QSPanel bigPanel = ctrl.getStatusBarView().findViewById(
+                    com.android.systemui.R.id.quick_settings_panel);
+            bigPanel.addMediaSession(token,
+                    mRow.getStatusBarNotification().getNotification().getSmallIcon(),
+                    getNotificationHeader().getOriginalIconColor(),
+                    mRow.getCurrentBackgroundTint(),
+                    mActions,
+                    mRow.getStatusBarNotification());
+        }
+
         boolean showCompactSeekbar = mMediaManager.getShowCompactMediaSeekbar();
         if (token == null || (COMPACT_MEDIA_TAG.equals(mView.getTag()) && !showCompactSeekbar)) {
             if (mSeekBarView != null) {
@@ -404,7 +428,7 @@
      * @return new LogMaker
      */
     private LogMaker newLog(int event) {
-        String packageName = mRow.getEntry().notification.getPackageName();
+        String packageName = mRow.getEntry().getSbn().getPackageName();
 
         return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
                 .setType(event)
@@ -416,7 +440,7 @@
      * @return new LogMaker
      */
     private LogMaker newLog(int event, int subtype) {
-        String packageName = mRow.getEntry().notification.getPackageName();
+        String packageName = mRow.getEntry().getSbn().getPackageName();
         return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
                 .setType(event)
                 .setSubtype(subtype)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 3950003..c2eff8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -63,7 +63,7 @@
                 return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
             }
             Class<? extends Notification.Style> style =
-                    row.getEntry().notification.getNotification().getNotificationStyle();
+                    row.getEntry().getSbn().getNotification().getNotificationStyle();
             if (Notification.DecoratedCustomViewStyle.class.equals(style)) {
                 return new NotificationDecoratedCustomViewWrapper(ctx, v, row);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index f3d068a..ecab188 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -22,7 +22,6 @@
 import android.util.MathUtils;
 import android.view.View;
 
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarState;
@@ -410,7 +409,7 @@
         if (!mPulsing || mHeadUpManager == null) {
             return false;
         }
-        return mHeadUpManager.isAlerting(entry.key);
+        return mHeadUpManager.isAlerting(entry.getKey());
     }
 
     public boolean isPanelTracking() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index d0444ae..54d4066 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -23,6 +23,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.PendingIntent;
 import android.content.Intent;
 import android.provider.Settings;
 import android.view.LayoutInflater;
@@ -33,6 +34,10 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.people.DataListener;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewBoundary;
+import com.android.systemui.statusbar.notification.people.PersonViewModel;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -42,6 +47,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import kotlin.sequences.Sequence;
+
 /**
  * Manages the boundaries of the two notification sections (high priority and low priority). Also
  * shows/hides the headers for those sections where appropriate.
@@ -58,11 +65,39 @@
     private final StatusBarStateController mStatusBarStateController;
     private final ConfigurationController mConfigurationController;
     private final int mNumberOfSections;
-
     private boolean mInitialized = false;
+
     private SectionHeaderView mGentleHeader;
     private boolean mGentleHeaderVisible = false;
 
+    private boolean mPeopleHubVisible = false;
+    private PeopleHubView mPeopleHubView;
+    private final PeopleHubSectionFooterViewAdapter mPeopleHubViewAdapter;
+    private final PeopleHubSectionFooterViewBoundary mPeopleHubViewBoundary =
+            new PeopleHubSectionFooterViewBoundary() {
+                @Override
+                public void setVisible(boolean isVisible) {
+                    if (mPeopleHubVisible != isVisible) {
+                        mPeopleHubVisible = isVisible;
+                        if (mInitialized) {
+                            updateSectionBoundaries();
+                        }
+                    }
+                }
+
+                @NonNull
+                @Override
+                public View getAssociatedViewForClickAnimation() {
+                    return mPeopleHubView;
+                }
+
+                @NonNull
+                @Override
+                public Sequence<DataListener<PersonViewModel>> getPersonViewAdapters() {
+                    return mPeopleHubView.getPersonViewAdapters();
+                }
+            };
+
     @Nullable private View.OnClickListener mOnClearGentleNotifsClickListener;
 
     NotificationSectionsManager(
@@ -70,11 +105,13 @@
             ActivityStarter activityStarter,
             StatusBarStateController statusBarStateController,
             ConfigurationController configurationController,
+            PeopleHubSectionFooterViewAdapter peopleHubViewAdapter,
             int numberOfSections) {
         mParent = parent;
         mActivityStarter = activityStarter;
         mStatusBarStateController = statusBarStateController;
         mConfigurationController = configurationController;
+        mPeopleHubViewAdapter = peopleHubViewAdapter;
         mNumberOfSections = numberOfSections;
     }
 
@@ -94,6 +131,7 @@
         }
         mInitialized = true;
         reinflateViews(layoutInflater);
+        mPeopleHubViewAdapter.bindView(mPeopleHubViewBoundary);
         mConfigurationController.addCallback(mConfigurationListener);
     }
 
@@ -101,23 +139,39 @@
      * Reinflates the entire notification header, including all decoration views.
      */
     void reinflateViews(LayoutInflater layoutInflater) {
-        int oldPos = -1;
+        int oldGentleHeaderPos = -1;
+        int oldPeopleHubPos = -1;
         if (mGentleHeader != null) {
             if (mGentleHeader.getTransientContainer() != null) {
                 mGentleHeader.getTransientContainer().removeView(mGentleHeader);
             } else if (mGentleHeader.getParent() != null) {
-                oldPos = mParent.indexOfChild(mGentleHeader);
+                oldGentleHeaderPos = mParent.indexOfChild(mGentleHeader);
                 mParent.removeView(mGentleHeader);
             }
         }
+        if (mPeopleHubView != null) {
+            if (mPeopleHubView.getTransientContainer() != null) {
+                mPeopleHubView.getTransientContainer().removeView(mPeopleHubView);
+            } else if (mPeopleHubView.getParent() != null) {
+                oldPeopleHubPos = mParent.indexOfChild(mPeopleHubView);
+                mParent.removeView(mPeopleHubView);
+            }
+        }
 
         mGentleHeader = (SectionHeaderView) layoutInflater.inflate(
                 R.layout.status_bar_notification_section_header, mParent, false);
         mGentleHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
         mGentleHeader.setOnClearAllClickListener(this::onClearGentleNotifsClick);
 
-        if (oldPos != -1) {
-            mParent.addView(mGentleHeader, oldPos);
+        if (oldGentleHeaderPos != -1) {
+            mParent.addView(mGentleHeader, oldGentleHeaderPos);
+        }
+
+        mPeopleHubView = (PeopleHubView) layoutInflater.inflate(
+                R.layout.people_strip, mParent, false);
+
+        if (oldPeopleHubPos != -1) {
+            mParent.addView(mPeopleHubView, oldPeopleHubPos);
         }
     }
 
@@ -145,7 +199,7 @@
         }
 
         if (!begin) {
-            begin = view == mGentleHeader;
+            begin = view == mGentleHeader || previous == mPeopleHubView;
         }
 
         return begin;
@@ -161,6 +215,8 @@
             return ((ExpandableNotificationRow) view).getEntry().getBucket();
         } else if (view == mGentleHeader) {
             return BUCKET_SILENT;
+        } else if (view == mPeopleHubView) {
+            return BUCKET_PEOPLE;
         }
 
         throw new IllegalArgumentException("I don't know how to find a bucket for this view :(");
@@ -175,6 +231,7 @@
             return;
         }
 
+        int lastPersonIndex = -1;
         int firstGentleNotifIndex = -1;
 
         final int n = mParent.getChildCount();
@@ -183,6 +240,9 @@
             if (child instanceof ExpandableNotificationRow
                     && child.getVisibility() != View.GONE) {
                 ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (row.getEntry().getBucket() == BUCKET_PEOPLE) {
+                    lastPersonIndex = i;
+                }
                 if (row.getEntry().getBucket() == BUCKET_SILENT) {
                     firstGentleNotifIndex = i;
                     break;
@@ -190,6 +250,11 @@
             }
         }
 
+        if (adjustPeopleHubVisibilityAndPosition(lastPersonIndex)) {
+            // make room for peopleHub
+            firstGentleNotifIndex++;
+        }
+
         adjustGentleHeaderVisibilityAndPosition(firstGentleNotifIndex);
 
         mGentleHeader.setAreThereDismissableGentleNotifs(
@@ -232,6 +297,36 @@
         }
     }
 
+    private boolean adjustPeopleHubVisibilityAndPosition(int lastPersonIndex) {
+        final boolean showPeopleHeader = mPeopleHubVisible
+                && mNumberOfSections > 2
+                && mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
+        final int currentHubIndex = mParent.indexOfChild(mPeopleHubView);
+        final boolean currentlyVisible = currentHubIndex >= 0;
+        int targetIndex = lastPersonIndex + 1;
+
+        if (!showPeopleHeader) {
+            if (currentlyVisible) {
+                mParent.removeView(mPeopleHubView);
+            }
+        } else {
+            if (!currentlyVisible) {
+                if (mPeopleHubView.getTransientContainer() != null) {
+                    mPeopleHubView.getTransientContainer().removeTransientView(mPeopleHubView);
+                    mPeopleHubView.setTransientContainer(null);
+                }
+                mParent.addView(mPeopleHubView, targetIndex);
+                return true;
+            } else if (currentHubIndex != targetIndex - 1) {
+                if (currentHubIndex < targetIndex) {
+                    targetIndex--;
+                }
+                mParent.changeViewPosition(mPeopleHubView, targetIndex);
+            }
+        }
+        return false;
+    }
+
     /**
      * Updates the boundaries (as tracked by their first and last views) of the priority sections.
      *
@@ -284,12 +379,12 @@
             ActivatableNotificationView first = s.getFirstVisibleChild();
             String fs = first == null ? "(null)"
                     :  (first instanceof ExpandableNotificationRow)
-                            ? ((ExpandableNotificationRow) first).getEntry().key
+                            ? ((ExpandableNotificationRow) first).getEntry().getKey()
                             : Integer.toHexString(System.identityHashCode(first));
             ActivatableNotificationView last = s.getLastVisibleChild();
             String ls = last == null ? "(null)"
                     :  (last instanceof ExpandableNotificationRow)
-                            ? ((ExpandableNotificationRow) last).getEntry().key
+                            ? ((ExpandableNotificationRow) last).getEntry().getKey()
                             : Integer.toHexString(System.identityHashCode(last));
             android.util.Log.d(TAG, "updateSections: f=" + fs + " s=" + i);
             android.util.Log.d(TAG, "updateSections: l=" + ls + " s=" + i);
@@ -324,6 +419,10 @@
         }
     }
 
+    private void handlePeopleHubClick(PendingIntent pendingIntent) {
+        mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent, null, mPeopleHubView);
+    }
+
     /**
      * For now, declare the available notification buckets (sections) here so that other
      * presentation code can decide what to do based on an entry's buckets
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 9817825..6dca7ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -116,6 +116,7 @@
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -518,7 +519,8 @@
             FalsingManager falsingManager,
             NotificationLockscreenUserManager notificationLockscreenUserManager,
             NotificationGutsManager notificationGutsManager,
-            NotificationSectionsFeatureManager sectionsFeatureManager) {
+            NotificationSectionsFeatureManager sectionsFeatureManager,
+            PeopleHubSectionFooterViewAdapter peopleHubViewAdapter) {
         super(context, attrs, 0, 0);
         Resources res = getResources();
 
@@ -541,6 +543,7 @@
                         activityStarter,
                         statusBarStateController,
                         configurationController,
+                        peopleHubViewAdapter,
                         buckets.length);
         mSectionsManager.initialize(LayoutInflater.from(context));
         mSectionsManager.setOnClearGentleNotifsClickListener(v -> {
@@ -602,7 +605,7 @@
         mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
             public void onPostEntryUpdated(NotificationEntry entry) {
-                if (!entry.notification.isClearable()) {
+                if (!entry.getSbn().isClearable()) {
                     // The user may have performed a dismiss action on the notification, since it's
                     // not clearable we should snap it back.
                     snapViewIfNeeded(entry);
@@ -1627,7 +1630,7 @@
                     if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
                             && mHeadsUpManager.getTopEntry().getRow() != row
                             && mGroupManager.getGroupSummary(
-                                mHeadsUpManager.getTopEntry().notification)
+                            mHeadsUpManager.getTopEntry().getSbn())
                             != entry) {
                         continue;
                     }
@@ -5525,12 +5528,12 @@
                         // TODO: This is a listener method; we shouldn't be calling it. Can we just
                         // call performRemoveNotification as below?
                         mEntryManager.removeNotification(
-                                rowToRemove.getEntry().key,
+                                rowToRemove.getEntry().getKey(),
                                 null /* ranking */,
                                 NotificationListenerService.REASON_CANCEL_ALL);
                     } else {
                         mEntryManager.performRemoveNotification(
-                                rowToRemove.getEntry().notification,
+                                rowToRemove.getEntry().getSbn(),
                                 NotificationListenerService.REASON_CANCEL_ALL);
                     }
                 } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
new file mode 100644
index 0000000..e31ee02
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.systemui.statusbar.notification.stack
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.android.systemui.R
+import com.android.systemui.statusbar.notification.people.PersonViewModel
+import com.android.systemui.statusbar.notification.people.DataListener
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
+
+class PeopleHubView(context: Context, attrs: AttributeSet) :
+        ActivatableNotificationView(context, attrs) {
+
+    private lateinit var contents: ViewGroup
+    private lateinit var personControllers: List<PersonDataListenerImpl>
+    val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
+        get() = personControllers.asSequence()
+
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        contents = requireViewById(R.id.people_list)
+        personControllers = (0 until contents.childCount)
+                .asSequence()
+                .mapNotNull { idx ->
+                    (contents.getChildAt(idx) as? LinearLayout)?.let(::PersonDataListenerImpl)
+                }
+                .toList()
+    }
+
+    override fun getContentView(): View = contents
+
+    private inner class PersonDataListenerImpl(val viewGroup: ViewGroup) :
+            DataListener<PersonViewModel?> {
+
+        val nameView = viewGroup.requireViewById<TextView>(R.id.person_name)
+        val avatarView = viewGroup.requireViewById<ImageView>(R.id.person_icon)
+
+        override fun onDataChanged(data: PersonViewModel?) {
+            viewGroup.visibility = data?.let { View.VISIBLE } ?: View.INVISIBLE
+            nameView.text = data?.name
+            avatarView.setImageDrawable(data?.icon)
+            viewGroup.setOnClickListener { data?.onClick?.invoke() }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index 175d072..f9b9367 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -16,62 +16,45 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
-
 import android.content.Context;
-import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.MotionEvent;
-import android.view.View;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 
 /** A controller to control all auto-hide things. */
-public class AutoHideController implements CommandQueue.Callbacks {
+public class AutoHideController {
     private static final String TAG = "AutoHideController";
 
     private final IWindowManager mWindowManagerService;
 
     private final Handler mHandler;
     private final NotificationRemoteInputManager mRemoteInputManager;
-    private final CommandQueue mCommandQueue;
     private StatusBar mStatusBar;
     private NavigationBarFragment mNavigationBar;
 
-    @VisibleForTesting
-    int mDisplayId;
-    @VisibleForTesting
-    int mSystemUiVisibility;
-    // last value sent to window manager
-    private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
+    private int mDisplayId;
 
     private boolean mAutoHideSuspended;
 
-    private static final long AUTOHIDE_TIMEOUT_MS = 2250;
+    private static final long AUTO_HIDE_TIMEOUT_MS = 2250;
 
     private final Runnable mAutoHide = () -> {
-        int requested = mSystemUiVisibility & ~getTransientMask();
-        if (mSystemUiVisibility != requested) {
-            notifySystemUiVisibilityChanged(requested);
+        if (isAnyTransientBarShown()) {
+            hideTransientBars();
         }
     };
 
     @Inject
-    public AutoHideController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler,
+    public AutoHideController(Context context, @MainHandler Handler handler,
             NotificationRemoteInputManager notificationRemoteInputManager,
             IWindowManager iWindowManager) {
-        mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
-        mCommandQueue.addCallback(this);
         mHandler = handler;
         mRemoteInputManager = notificationRemoteInputManager;
         mWindowManagerService = iWindowManager;
@@ -79,13 +62,6 @@
         mDisplayId = context.getDisplayId();
     }
 
-    @Override
-    public void onDisplayRemoved(int displayId) {
-        if (displayId == mDisplayId) {
-            mCommandQueue.removeCallback(this);
-        }
-    }
-
     void setStatusBar(StatusBar statusBar) {
         mStatusBar = statusBar;
     }
@@ -94,50 +70,18 @@
         mNavigationBar = navigationBar;
     }
 
-    @Override
-    public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
-            int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
-            boolean navbarColorManagedByIme) {
-        if (displayId != mDisplayId) {
-            return;
-        }
-        int oldVal = mSystemUiVisibility;
-        int newVal = (oldVal & ~mask) | (vis & mask);
-        int diff = newVal ^ oldVal;
-
-        if (diff != 0) {
-            mSystemUiVisibility = newVal;
-
-            // ready to unhide
-            if (hasStatusBar() && (vis & View.STATUS_BAR_UNHIDE) != 0) {
-                mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
-            }
-
-            if (hasNavigationBar() && (vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
-                mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
-            }
-
-            // Re-send setSystemUiVisibility to update un-hide status.
-            if (mSystemUiVisibility != newVal) {
-                mCommandQueue.setSystemUiVisibility(mDisplayId, mSystemUiVisibility,
-                        fullscreenStackVis, dockedStackVis, mask, fullscreenStackBounds,
-                        dockedStackBounds, navbarColorManagedByIme);
-            }
-
-            notifySystemUiVisibilityChanged(mSystemUiVisibility);
-        }
-    }
-
-    @VisibleForTesting
-    void notifySystemUiVisibilityChanged(int vis) {
+    private void hideTransientBars() {
         try {
-            if (mLastDispatchedSystemUiVisibility != vis) {
-                mWindowManagerService.statusBarVisibilityChanged(mDisplayId, vis);
-                mLastDispatchedSystemUiVisibility = vis;
-            }
+            mWindowManagerService.hideTransientBars(mDisplayId);
         } catch (RemoteException ex) {
             Log.w(TAG, "Cannot get WindowManager");
         }
+        if (mStatusBar != null) {
+            mStatusBar.clearTransient();
+        }
+        if (mNavigationBar != null) {
+            mNavigationBar.clearTransient();
+        }
     }
 
     void resumeSuspendedAutoHide() {
@@ -156,13 +100,12 @@
         if (checkBarModesRunnable != null) {
             mHandler.removeCallbacks(checkBarModesRunnable);
         }
-        mAutoHideSuspended = (mSystemUiVisibility & getTransientMask()) != 0;
+        mAutoHideSuspended = isAnyTransientBarShown();
     }
 
     void touchAutoHide() {
         // update transient bar auto hide
-        if ((hasStatusBar() && mStatusBar.getStatusBarMode() == MODE_SEMI_TRANSPARENT)
-                || hasNavigationBar() && mNavigationBar.isSemiTransparent()) {
+        if (isAnyTransientBarShown()) {
             scheduleAutoHide();
         } else {
             cancelAutoHide();
@@ -170,9 +113,9 @@
     }
 
     private Runnable getCheckBarModesRunnable() {
-        if (hasStatusBar()) {
+        if (mStatusBar != null) {
             return () -> mStatusBar.checkBarModes();
-        } else if (hasNavigationBar()) {
+        } else if (mNavigationBar != null) {
             return () -> mNavigationBar.checkNavBarModes();
         } else {
             return null;
@@ -186,15 +129,14 @@
 
     private void scheduleAutoHide() {
         cancelAutoHide();
-        mHandler.postDelayed(mAutoHide, AUTOHIDE_TIMEOUT_MS);
+        mHandler.postDelayed(mAutoHide, AUTO_HIDE_TIMEOUT_MS);
     }
 
     void checkUserAutoHide(MotionEvent event) {
-        boolean shouldAutoHide =
-                (mSystemUiVisibility & getTransientMask()) != 0  // a transient bar is revealed.
+        boolean shouldAutoHide = isAnyTransientBarShown()
                 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
                 && event.getX() == 0 && event.getY() == 0;
-        if (hasStatusBar()) {
+        if (mStatusBar != null) {
             // a touch outside both bars
             shouldAutoHide &= !mRemoteInputManager.getController().isRemoteInputActive();
         }
@@ -208,23 +150,8 @@
         mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
     }
 
-    private int getTransientMask() {
-        int mask = 0;
-        if (hasStatusBar()) {
-            mask |= View.STATUS_BAR_TRANSIENT;
-        }
-        if (hasNavigationBar()) {
-            mask |= View.NAVIGATION_BAR_TRANSIENT;
-        }
-        return mask;
-    }
-
-    boolean hasNavigationBar() {
-        return mNavigationBar != null;
-    }
-
-    @VisibleForTesting
-    boolean hasStatusBar() {
-        return mStatusBar != null;
+    private boolean isAnyTransientBarShown() {
+        return (mStatusBar != null && mStatusBar.isTransientShown())
+                || mNavigationBar != null && mNavigationBar.isTransientShown();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 007c50c..837517e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -21,7 +21,7 @@
 import android.provider.Settings.Secure;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
+import com.android.systemui.dagger.qualifiers.BgHandler;
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.SecureSetting;
@@ -33,7 +33,6 @@
 import com.android.systemui.statusbar.policy.HotspotController.Callback;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 
 /**
  * Manages which tiles should be automatically added to QS.
@@ -58,7 +57,7 @@
 
     @Inject
     public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
-            @Named(Dependency.BG_HANDLER_NAME) Handler handler,
+            @BgHandler Handler handler,
             HotspotController hotspotController,
             DataSaverController dataSaverController,
             ManagedProfileController managedProfileController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 211a40a..e6731e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -44,11 +44,11 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_COLORS = false;
 
-    public static final int MODE_OPAQUE = 0;
+    public static final int MODE_TRANSPARENT = 0;
     public static final int MODE_SEMI_TRANSPARENT = 1;
     public static final int MODE_TRANSLUCENT = 2;
     public static final int MODE_LIGHTS_OUT = 3;
-    public static final int MODE_TRANSPARENT = 4;
+    public static final int MODE_OPAQUE = 4;
     public static final int MODE_WARNING = 5;
     public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
 
@@ -72,7 +72,7 @@
     private final View mView;
     protected final BarBackgroundDrawable mBarBackground;
 
-    private int mMode;
+    private @TransitionMode int mMode;
     private boolean mAlwaysOpaque = false;
 
     public BarTransitions(View view, int gradientResourceId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 548afd5..ffcbc40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.content.Context;
+import android.content.res.Resources;
 import android.hardware.biometrics.BiometricSourceType;
 import android.metrics.LogMaker;
 import android.os.Handler;
@@ -34,6 +35,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.Dependency;
+import com.android.systemui.dagger.qualifiers.MainResources;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -44,15 +46,19 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Controller which coordinates all the biometric unlocking actions with the UI.
  */
+@Singleton
 public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
 
-    private static final String TAG = "BiometricUnlockController";
+    private static final String TAG = "BiometricUnlockCtrl";
     private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
     private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
-    private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
+    private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
 
     @IntDef(prefix = { "MODE_" }, value = {
             MODE_NONE,
@@ -128,7 +134,7 @@
     private final KeyguardBypassController mKeyguardBypassController;
     private PowerManager.WakeLock mWakeLock;
     private final KeyguardUpdateMonitor mUpdateMonitor;
-    private final DozeParameters mDozeParameters;
+    private DozeParameters mDozeParameters;
     private final KeyguardStateController mKeyguardStateController;
     private final StatusBarWindowController mStatusBarWindowController;
     private final Context mContext;
@@ -145,31 +151,16 @@
     private boolean mHasScreenTurnedOnSinceAuthenticating;
     private boolean mFadedAwayAfterWakeAndUnlock;
 
-    private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+    private final MetricsLogger mMetricsLogger;
 
-    public BiometricUnlockController(
-            Context context,
-            DozeScrimController dozeScrimController,
-            KeyguardViewMediator keyguardViewMediator,
-            ScrimController scrimController,
-            StatusBar statusBar,
-            KeyguardStateController keyguardStateController, Handler handler,
-            KeyguardUpdateMonitor keyguardUpdateMonitor,
-            KeyguardBypassController keyguardBypassController,
-            DozeParameters dozeParameters) {
-        this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar,
-                keyguardStateController, handler, keyguardUpdateMonitor,
-                context.getResources()
-                        .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze),
-                keyguardBypassController, dozeParameters);
-    }
-
-    @VisibleForTesting
-    protected BiometricUnlockController(Context context, DozeScrimController dozeScrimController,
+    @Inject
+    public BiometricUnlockController(Context context, DozeScrimController dozeScrimController,
             KeyguardViewMediator keyguardViewMediator, ScrimController scrimController,
             StatusBar statusBar, KeyguardStateController keyguardStateController, Handler handler,
-            KeyguardUpdateMonitor keyguardUpdateMonitor, int wakeUpDelay,
-            KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters) {
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            @MainResources Resources resources,
+            KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters,
+            MetricsLogger metricsLogger) {
         mContext = context;
         mPowerManager = context.getSystemService(PowerManager.class);
         mUpdateMonitor = keyguardUpdateMonitor;
@@ -185,9 +176,10 @@
         mStatusBar = statusBar;
         mKeyguardStateController = keyguardStateController;
         mHandler = handler;
-        mWakeUpDelay = wakeUpDelay;
+        mWakeUpDelay = resources.getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze);
         mKeyguardBypassController = keyguardBypassController;
         mKeyguardBypassController.setUnlockController(this);
+        mMetricsLogger = metricsLogger;
     }
 
     public void setStatusBarKeyguardViewManager(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 28dac87..bc48235 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -24,9 +24,8 @@
 import android.provider.Settings;
 import android.util.MathUtils;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.DependencyProvider;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainResources;
 import com.android.systemui.doze.AlwaysOnDisplayPolicy;
 import com.android.systemui.doze.DozeScreenState;
 import com.android.systemui.tuner.TunerService;
@@ -59,7 +58,7 @@
 
     @Inject
     protected DozeParameters(
-            @DependencyProvider.MainResources Resources resources,
+            @MainResources Resources resources,
             AmbientDisplayConfiguration ambientDisplayConfiguration,
             AlwaysOnDisplayPolicy alwaysOnDisplayPolicy,
             PowerManager powerManager,
@@ -188,12 +187,7 @@
             return;
         }
         mControlScreenOffAnimation = controlScreenOffAnimation;
-        getPowerManager().setDozeAfterScreenOff(!controlScreenOffAnimation);
-    }
-
-    @VisibleForTesting
-    protected PowerManager getPowerManager() {
-        return mPowerManager;
+        mPowerManager.setDozeAfterScreenOff(!controlScreenOffAnimation);
     }
 
     private boolean getBoolean(String propName, int resId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index fe3c04e..1ecc489 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -29,10 +29,12 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 
 import javax.inject.Inject;
+import javax.inject.Singleton;
 
 /**
  * Controller which handles all the doze animations of the scrims.
  */
+@Singleton
 public class DozeScrimController implements StateListener {
     private static final String TAG = "DozeScrimController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
new file mode 100644
index 0000000..2854355
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -0,0 +1,465 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.doze.DozeEvent;
+import com.android.systemui.doze.DozeHost;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.doze.DozeReceiver;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
+/**
+ * Implementation of DozeHost for SystemUI.
+ */
+@Singleton
+public final class DozeServiceHost implements DozeHost {
+    private static final String TAG = "DozeServiceHost";
+    private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+    private final DozeLog mDozeLog;
+    private final PowerManager mPowerManager;
+    private boolean mAnimateWakeup;
+    private boolean mAnimateScreenOff;
+    private boolean mIgnoreTouchWhilePulsing;
+    private Runnable mPendingScreenOffCallback;
+    @VisibleForTesting
+    boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean(
+            "persist.sysui.wake_performs_auth", true);
+    private boolean mDozingRequested;
+    private boolean mDozing;
+    private boolean mPulsing;
+    private WakefulnessLifecycle mWakefulnessLifecycle;
+    private final SysuiStatusBarStateController mStatusBarStateController;
+    private final DeviceProvisionedController mDeviceProvisionedController;
+    private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+    private final BatteryController mBatteryController;
+    private final ScrimController mScrimController;
+    private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
+    private BiometricUnlockController mBiometricUnlockController;
+    private final KeyguardViewMediator mKeyguardViewMediator;
+    private final AssistManager mAssistManager;
+    private final DozeScrimController mDozeScrimController;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final VisualStabilityManager mVisualStabilityManager;
+    private final PulseExpansionHandler mPulseExpansionHandler;
+    private final StatusBarWindowController mStatusBarWindowController;
+    private final NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
+    private NotificationIconAreaController mNotificationIconAreaController;
+    private StatusBarWindowViewController mStatusBarWindowViewController;
+    private StatusBarWindowView mStatusBarWindow;
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private NotificationPanelView mNotificationPanel;
+    private View mAmbientIndicationContainer;
+    private StatusBar mStatusBar;
+
+    @Inject
+    public DozeServiceHost(DozeLog dozeLog, PowerManager powerManager,
+            WakefulnessLifecycle wakefulnessLifecycle,
+            SysuiStatusBarStateController statusBarStateController,
+            DeviceProvisionedController deviceProvisionedController,
+            HeadsUpManagerPhone headsUpManagerPhone, BatteryController batteryController,
+            ScrimController scrimController,
+            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+            KeyguardViewMediator keyguardViewMediator,
+            AssistManager assistManager,
+            DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor,
+            VisualStabilityManager visualStabilityManager,
+            PulseExpansionHandler pulseExpansionHandler,
+            StatusBarWindowController statusBarWindowController,
+            NotificationWakeUpCoordinator notificationWakeUpCoordinator) {
+        super();
+        mDozeLog = dozeLog;
+        mPowerManager = powerManager;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
+        mStatusBarStateController = statusBarStateController;
+        mDeviceProvisionedController = deviceProvisionedController;
+        mHeadsUpManagerPhone = headsUpManagerPhone;
+        mBatteryController = batteryController;
+        mScrimController = scrimController;
+        mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+        mKeyguardViewMediator = keyguardViewMediator;
+        mAssistManager = assistManager;
+        mDozeScrimController = dozeScrimController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mVisualStabilityManager = visualStabilityManager;
+        mPulseExpansionHandler = pulseExpansionHandler;
+        mStatusBarWindowController = statusBarWindowController;
+        mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
+    }
+
+    // TODO: we should try to not pass status bar in here if we can avoid it.
+
+    /**
+     * Initialize instance with objects only available later during execution.
+     */
+    public void initialize(StatusBar statusBar,
+            NotificationIconAreaController notificationIconAreaController,
+            StatusBarWindowViewController statusBarWindowViewController,
+            StatusBarWindowView statusBarWindow,
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            NotificationPanelView notificationPanel, View ambientIndicationContainer) {
+        mStatusBar = statusBar;
+        mNotificationIconAreaController = notificationIconAreaController;
+        mStatusBarWindowViewController = statusBarWindowViewController;
+        mStatusBarWindow = statusBarWindow;
+        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+        mNotificationPanel = notificationPanel;
+        mAmbientIndicationContainer = ambientIndicationContainer;
+        mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
+    }
+
+    @Override
+    public String toString() {
+        return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
+    }
+
+    void firePowerSaveChanged(boolean active) {
+        for (Callback callback : mCallbacks) {
+            callback.onPowerSaveChanged(active);
+        }
+    }
+
+    void fireNotificationPulse(NotificationEntry entry) {
+        Runnable pulseSuppressedListener = () -> {
+            entry.setPulseSuppressed(true);
+            mNotificationIconAreaController.updateAodNotificationIcons();
+        };
+        for (Callback callback : mCallbacks) {
+            callback.onNotificationAlerted(pulseSuppressedListener);
+        }
+    }
+
+    boolean getDozingRequested() {
+        return mDozingRequested;
+    }
+
+    boolean isPulsing() {
+        return mPulsing;
+    }
+
+
+    @Override
+    public void addCallback(@NonNull Callback callback) {
+        mCallbacks.add(callback);
+    }
+
+    @Override
+    public void removeCallback(@NonNull Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    @Override
+    public void startDozing() {
+        if (!mDozingRequested) {
+            mDozingRequested = true;
+            mDozeLog.traceDozing(mDozing);
+            updateDozing();
+            mStatusBar.updateIsKeyguard();
+        }
+    }
+
+    void updateDozing() {
+        // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
+        boolean
+                dozing =
+                mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+                        || mBiometricUnlockController.getMode()
+                        == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+        // When in wake-and-unlock we may not have received a change to StatusBarState
+        // but we still should not be dozing, manually set to false.
+        if (mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
+            dozing = false;
+        }
+
+
+        mStatusBarStateController.setIsDozing(dozing);
+    }
+
+    @Override
+    public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
+        if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) {
+            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
+                                 "com.android.systemui:LONG_PRESS");
+            mAssistManager.startAssist(new Bundle());
+            return;
+        }
+
+        if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
+            mScrimController.setWakeLockScreenSensorActive(true);
+        }
+
+        if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
+            mStatusBarWindowViewController.suppressWakeUpGesture(true);
+        }
+
+        boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
+                        && mWakeLockScreenPerformsAuth;
+        // Set the state to pulsing, so ScrimController will know what to do once we ask it to
+        // execute the transition. The pulse callback will then be invoked when the scrims
+        // are black, indicating that StatusBar is ready to present the rest of the UI.
+        mPulsing = true;
+        mDozeScrimController.pulse(new PulseCallback() {
+            @Override
+            public void onPulseStarted() {
+                callback.onPulseStarted();
+                mStatusBar.updateNotificationPanelTouchState();
+                setPulsing(true);
+            }
+
+            @Override
+            public void onPulseFinished() {
+                mPulsing = false;
+                callback.onPulseFinished();
+                mStatusBar.updateNotificationPanelTouchState();
+                mScrimController.setWakeLockScreenSensorActive(false);
+                if (mStatusBarWindow != null) {
+                    mStatusBarWindowViewController.suppressWakeUpGesture(false);
+                }
+                setPulsing(false);
+            }
+
+            private void setPulsing(boolean pulsing) {
+                mStatusBarStateController.setPulsing(pulsing);
+                mStatusBarKeyguardViewManager.setPulsing(pulsing);
+                mKeyguardViewMediator.setPulsing(pulsing);
+                mNotificationPanel.setPulsing(pulsing);
+                mVisualStabilityManager.setPulsing(pulsing);
+                mStatusBarWindowViewController.setPulsing(pulsing);
+                mIgnoreTouchWhilePulsing = false;
+                if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
+                    mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
+                }
+                mStatusBar.updateScrimController();
+                mPulseExpansionHandler.setPulsing(pulsing);
+                mNotificationWakeUpCoordinator.setPulsing(pulsing);
+            }
+        }, reason);
+        // DozeScrimController is in pulse state, now let's ask ScrimController to start
+        // pulsing and draw the black frame, if necessary.
+        mStatusBar.updateScrimController();
+    }
+
+    @Override
+    public void stopDozing() {
+        if (mDozingRequested) {
+            mDozingRequested = false;
+            mDozeLog.traceDozing(mDozing);
+            updateDozing();
+        }
+    }
+
+    @Override
+    public void onIgnoreTouchWhilePulsing(boolean ignore) {
+        if (ignore != mIgnoreTouchWhilePulsing) {
+            mDozeLog.tracePulseTouchDisabledByProx(ignore);
+        }
+        mIgnoreTouchWhilePulsing = ignore;
+        if (mDozing && ignore) {
+            mStatusBarWindowViewController.cancelCurrentTouch();
+        }
+    }
+
+    @Override
+    public void dozeTimeTick() {
+        mNotificationPanel.dozeTimeTick();
+        if (mAmbientIndicationContainer instanceof DozeReceiver) {
+            ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
+        }
+    }
+
+    @Override
+    public boolean isPowerSaveActive() {
+        return mBatteryController.isAodPowerSave();
+    }
+
+    @Override
+    public boolean isPulsingBlocked() {
+        return mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
+    }
+
+    @Override
+    public boolean isProvisioned() {
+        return mDeviceProvisionedController.isDeviceProvisioned()
+                && mDeviceProvisionedController.isCurrentUserSetup();
+    }
+
+    @Override
+    public boolean isBlockingDoze() {
+        if (mBiometricUnlockController.hasPendingAuthentication()) {
+            Log.i(StatusBar.TAG, "Blocking AOD because fingerprint has authenticated");
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void extendPulse(int reason) {
+        if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
+            mScrimController.setWakeLockScreenSensorActive(true);
+        }
+        if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) {
+            mHeadsUpManagerPhone.extendHeadsUp();
+        } else {
+            mDozeScrimController.extendPulse();
+        }
+    }
+
+    @Override
+    public void stopPulsing() {
+        if (mDozeScrimController.isPulsing()) {
+            mDozeScrimController.pulseOutNow();
+        }
+    }
+
+    @Override
+    public void setAnimateWakeup(boolean animateWakeup) {
+        if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
+                || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) {
+            // Too late to change the wakeup animation.
+            return;
+        }
+        mAnimateWakeup = animateWakeup;
+    }
+
+    @Override
+    public void setAnimateScreenOff(boolean animateScreenOff) {
+        mAnimateScreenOff = animateScreenOff;
+    }
+
+    @Override
+    public void onSlpiTap(float screenX, float screenY) {
+        if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
+                && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
+            int[] locationOnScreen = new int[2];
+            mAmbientIndicationContainer.getLocationOnScreen(locationOnScreen);
+            float viewX = screenX - locationOnScreen[0];
+            float viewY = screenY - locationOnScreen[1];
+            if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
+                    && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
+
+                // Dispatch a tap
+                long now = SystemClock.elapsedRealtime();
+                MotionEvent ev = MotionEvent.obtain(
+                        now, now, MotionEvent.ACTION_DOWN, screenX, screenY, 0);
+                mAmbientIndicationContainer.dispatchTouchEvent(ev);
+                ev.recycle();
+                ev = MotionEvent.obtain(
+                        now, now, MotionEvent.ACTION_UP, screenX, screenY, 0);
+                mAmbientIndicationContainer.dispatchTouchEvent(ev);
+                ev.recycle();
+            }
+        }
+    }
+
+    @Override
+    public void setDozeScreenBrightness(int value) {
+        mStatusBarWindowController.setDozeScreenBrightness(value);
+    }
+
+    @Override
+    public void setAodDimmingScrim(float scrimOpacity) {
+        mScrimController.setAodFrontScrimAlpha(scrimOpacity);
+    }
+
+
+
+    @Override
+    public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
+        if (mPendingScreenOffCallback != null) {
+            Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one.");
+        }
+        mPendingScreenOffCallback = onDisplayOffCallback;
+        mStatusBar.updateScrimController();
+    }
+
+    @Override
+    public void cancelGentleSleep() {
+        mPendingScreenOffCallback = null;
+        if (mScrimController.getState() == ScrimState.OFF) {
+            mStatusBar.updateScrimController();
+        }
+    }
+
+    /**
+     * When the dozing host is waiting for scrims to fade out to change the display state.
+     */
+    boolean hasPendingScreenOffCallback() {
+        return mPendingScreenOffCallback != null;
+    }
+
+    /**
+     * Executes an nullifies the pending display state callback.
+     *
+     * @see #hasPendingScreenOffCallback()
+     * @see #prepareForGentleSleep(Runnable)
+     */
+    void executePendingScreenOffCallback() {
+        if (mPendingScreenOffCallback == null) {
+            return;
+        }
+        mPendingScreenOffCallback.run();
+        mPendingScreenOffCallback = null;
+    }
+
+    boolean shouldAnimateWakeup() {
+        return mAnimateWakeup;
+    }
+
+    boolean shouldAnimateScreenOff() {
+        return mAnimateScreenOff;
+    }
+
+    public void setDozing(boolean dozing) {
+        mDozing = dozing;
+    }
+
+    boolean getIgnoreTouchWhilePulsing() {
+        return mIgnoreTouchWhilePulsing;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 442c089..1c8e832 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -16,8 +16,6 @@
 package com.android.systemui.statusbar.phone;
 
 import static android.view.Display.INVALID_DISPLAY;
-import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-import static android.view.View.NAVIGATION_BAR_TRANSIENT;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -56,9 +54,7 @@
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
 import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.WindowManagerWrapper;
 
 import java.io.PrintWriter;
 import java.util.concurrent.Executor;
@@ -72,15 +68,6 @@
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
             "gestures.back_timeout", 250);
 
-    private final PinnedStackListener mImeChangedListener = new PinnedStackListener() {
-        @Override
-        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
-            // No need to thread jump, assignments are atomic
-            mImeHeight = imeVisible ? imeHeight : 0;
-            // TODO: Probably cancel any existing gesture
-        }
-    };
-
     private ISystemGestureExclusionListener mGestureExclusionListener =
             new ISystemGestureExclusionListener.Stub() {
                 @Override
@@ -128,12 +115,10 @@
     private boolean mInRejectedExclusion = false;
     private boolean mIsOnLeftEdge;
 
-    private int mImeHeight = 0;
-
     private boolean mIsAttached;
     private boolean mIsGesturalModeEnabled;
     private boolean mIsEnabled;
-    private boolean mIsInTransientImmersiveStickyState;
+    private boolean mIsNavBarShownTransiently;
 
     private InputMonitor mInputMonitor;
     private InputEventReceiver mInputEventReceiver;
@@ -198,10 +183,8 @@
         updateCurrentUserResources(currentUserContext.getResources());
     }
 
-    public void onSystemUiVisibilityChanged(int systemUiVisibility) {
-        mIsInTransientImmersiveStickyState =
-                (systemUiVisibility & SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0
-                && (systemUiVisibility & NAVIGATION_BAR_TRANSIENT) != 0;
+    public void onNavBarTransientStateChanged(boolean isTransient) {
+        mIsNavBarShownTransiently = isTransient;
     }
 
     private void disposeInputChannel() {
@@ -231,7 +214,6 @@
         }
 
         if (!mIsEnabled) {
-            WindowManagerWrapper.getInstance().removePinnedStackListener(mImeChangedListener);
             mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
 
             try {
@@ -248,7 +230,6 @@
                     mContext.getMainThreadHandler());
 
             try {
-                WindowManagerWrapper.getInstance().addPinnedStackListener(mImeChangedListener);
                 WindowManagerGlobal.getWindowManagerService()
                         .registerSystemGestureExclusionListener(
                                 mGestureExclusionListener, mDisplayId);
@@ -305,18 +286,13 @@
     }
 
     private boolean isWithinTouchRegion(int x, int y) {
-        // Disallow if over the IME
-        if (y > (mDisplaySize.y - Math.max(mImeHeight, mNavBarHeight))) {
-            return false;
-        }
-
         // Disallow if too far from the edge
         if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
             return false;
         }
 
         // Always allow if the user is in a transient sticky immersive state
-        if (mIsInTransientImmersiveStickyState) {
+        if (mIsNavBarShownTransiently) {
             return true;
         }
 
@@ -487,7 +463,6 @@
         pw.println("  mInRejectedExclusion" + mInRejectedExclusion);
         pw.println("  mExcludeRegion=" + mExcludeRegion);
         pw.println("  mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
-        pw.println("  mImeHeight=" + mImeHeight);
         pw.println("  mIsAttached=" + mIsAttached);
         pw.println("  mEdgeWidth=" + mEdgeWidth);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index c6d051d..4e06c84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -197,9 +197,9 @@
             mReleaseOnExpandFinish = false;
         } else {
             for (NotificationEntry entry : mEntriesToRemoveAfterExpand) {
-                if (isAlerting(entry.key)) {
+                if (isAlerting(entry.getKey())) {
                     // Maybe the heads-up was removed already
-                    removeAlertEntry(entry.key);
+                    removeAlertEntry(entry.getKey());
                 }
             }
         }
@@ -291,7 +291,7 @@
      */
     public void setRemoteInputActive(
             @NonNull NotificationEntry entry, boolean remoteInputActive) {
-        HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.key);
+        HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.getKey());
         if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
             headsUpEntry.remoteInputActive = remoteInputActive;
             if (remoteInputActive) {
@@ -307,7 +307,7 @@
      * area if it's pinned until it's hidden again.
      */
     public void setMenuShown(@NonNull NotificationEntry entry, boolean menuShown) {
-        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.key);
+        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
         if (headsUpEntry instanceof HeadsUpEntryPhone && entry.isRowPinned()) {
             ((HeadsUpEntryPhone) headsUpEntry).setMenuShownPinned(menuShown);
         }
@@ -375,7 +375,7 @@
         } else {
             if (topEntry.isChildInGroup()) {
                 final NotificationEntry groupSummary =
-                        mGroupManager.getGroupSummary(topEntry.notification);
+                        mGroupManager.getGroupSummary(topEntry.getSbn());
                 if (groupSummary != null) {
                     topEntry = groupSummary;
                 }
@@ -429,9 +429,9 @@
     public void onReorderingAllowed() {
         mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
         for (NotificationEntry entry : mEntriesToRemoveWhenReorderingAllowed) {
-            if (isAlerting(entry.key)) {
+            if (isAlerting(entry.getKey())) {
                 // Maybe the heads-up was removed already
-                removeAlertEntry(entry.key);
+                removeAlertEntry(entry.getKey());
             }
         }
         mEntriesToRemoveWhenReorderingAllowed.clear();
@@ -448,7 +448,7 @@
 
     @Override
     protected void onAlertEntryRemoved(AlertEntry alertEntry) {
-        mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.key);
+        mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.getKey());
         super.onAlertEntryRemoved(alertEntry);
         mEntryPool.release((HeadsUpEntryPhone) alertEntry);
     }
@@ -533,9 +533,9 @@
                 } else if (mTrackingHeadsUp) {
                     mEntriesToRemoveAfterExpand.add(entry);
                 } else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
-                    mKeysToRemoveWhenLeavingKeyguard.add(entry.key);
+                    mKeysToRemoveWhenLeavingKeyguard.add(entry.getKey());
                 } else {
-                    removeAlertEntry(entry.key);
+                    removeAlertEntry(entry.getKey());
                 }
             };
 
@@ -553,7 +553,7 @@
             if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
                 mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
             }
-            mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.key);
+            mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.getKey());
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index dd200da..7f31f3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -77,9 +77,12 @@
                 ExpandableView child = mCallback.getChildAtRawPosition(x, y);
                 mTouchingHeadsUpView = false;
                 if (child instanceof ExpandableNotificationRow) {
-                    mPickedChild = (ExpandableNotificationRow) child;
+                    ExpandableNotificationRow pickedChild = (ExpandableNotificationRow) child;
                     mTouchingHeadsUpView = !mCallback.isExpanded()
-                            && mPickedChild.isHeadsUp() && mPickedChild.isPinned();
+                            && pickedChild.isHeadsUp() && pickedChild.isPinned();
+                    if (mTouchingHeadsUpView) {
+                        mPickedChild = pickedChild;
+                    }
                 } else if (child == null && !mCallback.isExpanded()) {
                     // We might touch above the visible heads up child, but then we still would
                     // like to capture it.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index d9de59e..bf88704 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -21,17 +21,16 @@
 import android.hardware.TriggerEventListener
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.Dependency
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.util.Assert
 import com.android.systemui.util.sensors.AsyncSensorManager
 
 class KeyguardLiftController constructor(
     private val statusBarStateController: StatusBarStateController,
-    private val asyncSensorManager: AsyncSensorManager
+    private val asyncSensorManager: AsyncSensorManager,
+    private val keyguardUpdateMonitor: KeyguardUpdateMonitor
 ) : StatusBarStateController.StateListener, KeyguardUpdateMonitorCallback() {
 
-    private val keyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor::class.java)
     private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
     private var isListening = false
     private var bouncerVisible = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index b0b656a..2e776e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,15 +16,20 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
 
 import android.content.Context;
 import android.graphics.Color;
-import android.graphics.Rect;
-import android.view.View;
+import android.view.InsetsFlags;
+import android.view.ViewDebug;
+import android.view.WindowInsetsController.Appearance;
 
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
+import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
@@ -49,13 +54,10 @@
     private BiometricUnlockController mBiometricUnlockController;
 
     private LightBarTransitionsController mNavigationBarController;
-    private int mSystemUiVisibility;
-    private int mFullscreenStackVisibility;
-    private int mDockedStackVisibility;
-    private boolean mFullscreenLight;
-    private boolean mDockedLight;
-    private int mLastStatusBarMode;
-    private int mLastNavigationBarMode;
+    private @Appearance int mAppearance;
+    private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
+    private int mStatusBarMode;
+    private int mNavigationBarMode;
     private final Color mDarkModeColor;
 
     /**
@@ -75,8 +77,6 @@
      */
     private boolean mForceDarkForScrim;
 
-    private final Rect mLastFullscreenBounds = new Rect();
-    private final Rect mLastDockedBounds = new Rect();
     private boolean mQsCustomizing;
 
     private boolean mDirectReplying;
@@ -101,45 +101,32 @@
         mBiometricUnlockController = biometricUnlockController;
     }
 
-    public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis,
-            int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
+    void onStatusBarAppearanceChanged(AppearanceRegion[] appearanceRegions, boolean sbModeChanged,
             int statusBarMode, boolean navbarColorManagedByIme) {
-        int oldFullscreen = mFullscreenStackVisibility;
-        int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
-        int diffFullscreen = newFullscreen ^ oldFullscreen;
-        int oldDocked = mDockedStackVisibility;
-        int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
-        int diffDocked = newDocked ^ oldDocked;
-        if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
-                || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
-                || sbModeChanged
-                || !mLastFullscreenBounds.equals(fullscreenStackBounds)
-                || !mLastDockedBounds.equals(dockedStackBounds)) {
-
-            mFullscreenLight = isLight(newFullscreen, statusBarMode,
-                    View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
-            mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
-            updateStatus(fullscreenStackBounds, dockedStackBounds);
+        final int numStacks = appearanceRegions.length;
+        boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks;
+        for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
+            stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
         }
-
-        mFullscreenStackVisibility = newFullscreen;
-        mDockedStackVisibility = newDocked;
-        mLastStatusBarMode = statusBarMode;
+        if (stackAppearancesChanged || sbModeChanged) {
+            mAppearanceRegions = appearanceRegions;
+            onStatusBarModeChanged(statusBarMode);
+        }
         mNavbarColorManagedByIme = navbarColorManagedByIme;
-        mLastFullscreenBounds.set(fullscreenStackBounds);
-        mLastDockedBounds.set(dockedStackBounds);
     }
 
-    public void onNavigationVisibilityChanged(int vis, int mask, boolean nbModeChanged,
+    void onStatusBarModeChanged(int newBarMode) {
+        mStatusBarMode = newBarMode;
+        updateStatus();
+    }
+
+    void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
             int navigationBarMode, boolean navbarColorManagedByIme) {
-        int oldVis = mSystemUiVisibility;
-        int newVis = (oldVis & ~mask) | (vis & mask);
-        int diffVis = newVis ^ oldVis;
-        if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
-                || nbModeChanged) {
-            boolean last = mNavigationLight;
-            mHasLightNavigationBar = isLight(vis, navigationBarMode,
-                    View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+        int diff = appearance ^ mAppearance;
+        if ((diff & APPEARANCE_LIGHT_SIDE_BARS) != 0 || nbModeChanged) {
+            final boolean last = mNavigationLight;
+            mHasLightNavigationBar = isLight(appearance, navigationBarMode,
+                    APPEARANCE_LIGHT_SIDE_BARS);
             mNavigationLight = mHasLightNavigationBar
                     && (mDirectReplying && mNavbarColorManagedByIme || !mForceDarkForScrim)
                     && !mQsCustomizing;
@@ -147,17 +134,20 @@
                 updateNavigation();
             }
         }
-        mSystemUiVisibility = newVis;
-        mLastNavigationBarMode = navigationBarMode;
+        mAppearance = appearance;
+        mNavigationBarMode = navigationBarMode;
         mNavbarColorManagedByIme = navbarColorManagedByIme;
     }
 
+    void onNavigationBarModeChanged(int newBarMode) {
+        mHasLightNavigationBar = isLight(mAppearance, newBarMode, APPEARANCE_LIGHT_SIDE_BARS);
+    }
+
     private void reevaluate() {
-        onSystemUiVisibilityChanged(mFullscreenStackVisibility,
-                mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
-                true /* sbModeChange*/, mLastStatusBarMode, mNavbarColorManagedByIme);
-        onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */, true /* nbModeChanged */,
-                mLastNavigationBarMode, mNavbarColorManagedByIme);
+        onStatusBarAppearanceChanged(mAppearanceRegions, true /* sbModeChange */, mStatusBarMode,
+                mNavbarColorManagedByIme);
+        onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */,
+                mNavigationBarMode, mNavbarColorManagedByIme);
     }
 
     public void setQsCustomizing(boolean customizing) {
@@ -191,10 +181,10 @@
         }
     }
 
-    private boolean isLight(int vis, int barMode, int flag) {
-        boolean isTransparentBar = (barMode == MODE_TRANSPARENT
+    private static boolean isLight(int appearance, int barMode, int flag) {
+        final boolean isTransparentBar = (barMode == MODE_TRANSPARENT
                 || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
-        boolean light = (vis & flag) != 0;
+        final boolean light = (appearance & flag) != 0;
         return isTransparentBar && light;
     }
 
@@ -207,49 +197,49 @@
                 && unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
     }
 
-    private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
-        boolean hasDockedStack = !dockedStackBounds.isEmpty();
+    private void updateStatus() {
+        final int numStacks = mAppearanceRegions.length;
+        int numLightStacks = 0;
 
-        // If both are light or fullscreen is light and there is no docked stack, all icons get
-        // dark.
-        if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
+        // We can only have maximum one light stack.
+        int indexLightStack = -1;
+
+        for (int i = 0; i < numStacks; i++) {
+            if (isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
+                    APPEARANCE_LIGHT_TOP_BAR)) {
+                numLightStacks++;
+                indexLightStack = i;
+            }
+        }
+
+        // If all stacks are light, all icons get dark.
+        if (numLightStacks == numStacks) {
             mStatusBarIconController.setIconsDarkArea(null);
             mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
 
         }
 
-        // If no one is light or the fullscreen is not light and there is no docked stack,
-        // all icons become white.
-        else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
+        // If no one is light, all icons become white.
+        else if (numLightStacks == 0) {
             mStatusBarIconController.getTransitionsController().setIconsDark(
                     false, animateChange());
         }
 
         // Not the same for every stack, magic!
         else {
-            Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
-            if (bounds.isEmpty()) {
-                mStatusBarIconController.setIconsDarkArea(null);
-            } else {
-                mStatusBarIconController.setIconsDarkArea(bounds);
-            }
+            mStatusBarIconController.setIconsDarkArea(
+                    mAppearanceRegions[indexLightStack].getBounds());
             mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
         }
     }
 
     private void updateNavigation() {
         if (mNavigationBarController != null) {
-            mNavigationBarController.setIconsDark(
-                    mNavigationLight, animateChange());
+            mNavigationBarController.setIconsDark(mNavigationLight, animateChange());
         }
     }
 
     @Override
-    public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-
-    }
-
-    @Override
     public void onPowerSaveChanged(boolean isPowerSave) {
         reevaluate();
     }
@@ -257,24 +247,21 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("LightBarController: ");
-        pw.print(" mSystemUiVisibility=0x"); pw.print(
-                Integer.toHexString(mSystemUiVisibility));
-        pw.print(" mFullscreenStackVisibility=0x"); pw.print(
-                Integer.toHexString(mFullscreenStackVisibility));
-        pw.print(" mDockedStackVisibility=0x"); pw.println(
-                Integer.toHexString(mDockedStackVisibility));
-
-        pw.print(" mFullscreenLight="); pw.print(mFullscreenLight);
-        pw.print(" mDockedLight="); pw.println(mDockedLight);
-
-        pw.print(" mLastFullscreenBounds="); pw.print(mLastFullscreenBounds);
-        pw.print(" mLastDockedBounds="); pw.println(mLastDockedBounds);
+        pw.print(" mAppearance=0x"); pw.println(ViewDebug.flagsToString(
+                InsetsFlags.class, "appearance", mAppearance));
+        final int numStacks = mAppearanceRegions.length;
+        for (int i = 0; i < numStacks; i++) {
+            final boolean isLight = isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
+                    APPEARANCE_LIGHT_TOP_BAR);
+            pw.print(" stack #"); pw.print(i); pw.print(": ");
+            pw.print(mAppearanceRegions[i].toString()); pw.print(" isLight="); pw.println(isLight);
+        }
 
         pw.print(" mNavigationLight="); pw.print(mNavigationLight);
         pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar);
 
-        pw.print(" mLastStatusBarMode="); pw.print(mLastStatusBarMode);
-        pw.print(" mLastNavigationBarMode="); pw.println(mLastNavigationBarMode);
+        pw.print(" mStatusBarMode="); pw.print(mStatusBarMode);
+        pw.print(" mNavigationBarMode="); pw.println(mNavigationBarMode);
 
         pw.print(" mForceDarkForScrim="); pw.print(mForceDarkForScrim);
         pw.print(" mQsCustomizing="); pw.print(mQsCustomizing);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index e34c639..4d6b54c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -22,7 +22,6 @@
 import android.app.IWallpaperManagerCallback;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
-import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -35,7 +34,6 @@
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.util.Log;
 
@@ -47,9 +45,13 @@
 
 import java.util.Objects;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Manages the lockscreen wallpaper.
  */
+@Singleton
 public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implements Runnable {
 
     private static final String TAG = "LockscreenWallpaper";
@@ -57,9 +59,8 @@
     private final NotificationMediaManager mMediaManager =
             Dependency.get(NotificationMediaManager.class);
 
-    private final StatusBar mBar;
     private final WallpaperManager mWallpaperManager;
-    private final Handler mH;
+    private Handler mH;
     private final KeyguardUpdateMonitor mUpdateMonitor;
 
     private boolean mCached;
@@ -70,25 +71,32 @@
     private UserHandle mSelectedUser;
     private AsyncTask<Void, Void, LoaderResult> mLoader;
 
-    public LockscreenWallpaper(Context ctx, StatusBar bar, Handler h) {
-        mBar = bar;
-        mH = h;
-        mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE);
+    @Inject
+    public LockscreenWallpaper(WallpaperManager wallpaperManager,
+            @Nullable IWallpaperManager iWallpaperManager,
+            KeyguardUpdateMonitor keyguardUpdateMonitor) {
+        mWallpaperManager = wallpaperManager;
         mCurrentUserId = ActivityManager.getCurrentUser();
-        mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+        mUpdateMonitor = keyguardUpdateMonitor;
 
-        IWallpaperManager service = IWallpaperManager.Stub.asInterface(
-                ServiceManager.getService(Context.WALLPAPER_SERVICE));
-        if (service != null) {
+        if (iWallpaperManager != null) {
             // Service is disabled on some devices like Automotive
             try {
-                service.setLockWallpaperCallback(this);
+                iWallpaperManager.setLockWallpaperCallback(this);
             } catch (RemoteException e) {
                 Log.e(TAG, "System dead?" + e);
             }
         }
     }
 
+    void setHandler(Handler handler) {
+        if (mH != null) {
+            Log.wtfStack(TAG, "Handler has already been set. Trying to double initialize?");
+            return;
+        }
+        mH = handler;
+    }
+
     public Bitmap getBitmap() {
         if (mCached) {
             return mCache;
@@ -176,6 +184,10 @@
     }
 
     private void postUpdateWallpaper() {
+        if (mH == null) {
+            Log.wtfStack(TAG, "Trying to use LockscreenWallpaper before initialization.");
+            return;
+        }
         mH.removeCallbacks(this);
         mH.post(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 38dc5ea..7030dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -21,6 +21,10 @@
 import static android.app.StatusBarManager.WindowType;
 import static android.app.StatusBarManager.WindowVisibleState;
 import static android.app.StatusBarManager.windowStateToString;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_SIDE_BARS;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
 
 import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
@@ -31,7 +35,6 @@
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
@@ -52,7 +55,6 @@
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.graphics.PixelFormat;
-import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
 import android.os.Binder;
@@ -67,12 +69,14 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Display;
+import android.view.InsetsState.InternalInsetType;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowInsetsController.Appearance;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
@@ -84,6 +88,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.LatencyTracker;
+import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
@@ -128,7 +133,8 @@
     private static final boolean DEBUG = false;
     private static final String EXTRA_DISABLE_STATE = "disabled_state";
     private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
-    private static final String EXTRA_SYSTEM_UI_VISIBILITY = "system_ui_visibility";
+    private static final String EXTRA_APPEARANCE = "appearance";
+    private static final String EXTRA_TRANSIENT_STATE = "transient_state";
 
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -165,7 +171,10 @@
     private Locale mLocale;
     private int mLayoutDirection;
 
-    private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+    /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+    private @Appearance int mAppearance;
+
+    private boolean mTransientShown;
     private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
     private LightBarController mLightBarController;
     private AutoHideController mAutoHideController;
@@ -295,7 +304,8 @@
         if (savedInstanceState != null) {
             mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
             mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
-            mSystemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
+            mAppearance = savedInstanceState.getInt(EXTRA_APPEARANCE, 0);
+            mTransientShown = savedInstanceState.getBoolean(EXTRA_TRANSIENT_STATE, false);
         }
         mAccessibilityManagerWrapper.addCallback(mAccessibilityListener);
 
@@ -397,7 +407,8 @@
         super.onSaveInstanceState(outState);
         outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
         outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2);
-        outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
+        outState.putInt(EXTRA_APPEARANCE, mAppearance);
+        outState.putBoolean(EXTRA_TRANSIENT_STATE, mTransientShown);
         if (mNavigationBarView != null) {
             mNavigationBarView.getLightTransitionsController().saveState(outState);
         }
@@ -518,80 +529,107 @@
         rotationButtonController.onRotationProposal(rotation, winRotation, isValid);
     }
 
-    /** Restores the System UI flags saved state to {@link NavigationBarFragment}. */
-    public void restoreSystemUiVisibilityState() {
-        final int barMode = computeBarMode(0, mSystemUiVisibility);
-        if (barMode != -1) {
-            mNavigationBarMode = barMode;
-        }
+    /** Restores the appearance and the transient saved state to {@link NavigationBarFragment}. */
+    public void restoreAppearanceAndTransientState() {
+        final int barMode = barMode(mTransientShown, mAppearance);
+        mNavigationBarMode = barMode;
         checkNavBarModes();
         mAutoHideController.touchAutoHide();
 
-        mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
-                true /* nbModeChanged */, mNavigationBarMode, false /* navbarColorManagedByIme */);
+        mLightBarController.onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */,
+                barMode, false /* navbarColorManagedByIme */);
     }
 
     @Override
-    public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
-            int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
-            boolean navbarColorManagedByIme) {
+    public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+            AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
         if (displayId != mDisplayId) {
             return;
         }
-        final int oldVal = mSystemUiVisibility;
-        final int newVal = (oldVal & ~mask) | (vis & mask);
-        final int diff = newVal ^ oldVal;
         boolean nbModeChanged = false;
-        if (diff != 0) {
-            mSystemUiVisibility = newVal;
-
-            // update navigation bar mode
-            final int nbMode = getView() == null
-                    ? -1 : computeBarMode(oldVal, newVal);
-            nbModeChanged = nbMode != -1;
-            if (nbModeChanged) {
-                if (mNavigationBarMode != nbMode) {
-                    if (mNavigationBarMode == MODE_TRANSPARENT
-                            || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
-                        mNavigationBarView.hideRecentsOnboarding();
-                    }
-                    mNavigationBarMode = nbMode;
-                    checkNavBarModes();
-                }
-                mAutoHideController.touchAutoHide();
+        if (mAppearance != appearance) {
+            mAppearance = appearance;
+            if (getView() == null) {
+                return;
             }
-            if (mNavigationBarView != null) {
-                mNavigationBarView.onSystemUiVisibilityChanged(mSystemUiVisibility);
-            }
+            nbModeChanged = updateBarMode(barMode(mTransientShown, appearance));
         }
-        mLightBarController.onNavigationVisibilityChanged(
-                vis, mask, nbModeChanged, mNavigationBarMode, navbarColorManagedByIme);
+        mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged,
+                mNavigationBarMode, navbarColorManagedByIme);
     }
 
-    private @TransitionMode int computeBarMode(int oldVis, int newVis) {
-        final int oldMode = barMode(oldVis);
-        final int newMode = barMode(newVis);
-        if (oldMode == newMode) {
-            return -1; // no mode change
+    @Override
+    public void showTransient(int displayId, @InternalInsetType int[] types) {
+        if (displayId != mDisplayId) {
+            return;
         }
-        return newMode;
+        if (!containsType(types, TYPE_NAVIGATION_BAR)) {
+            return;
+        }
+        if (!mTransientShown) {
+            mTransientShown = true;
+            handleTransientChanged();
+        }
     }
 
-    private @TransitionMode int barMode(int vis) {
-        final int lightsOutTransparent =
-                View.SYSTEM_UI_FLAG_LOW_PROFILE | View.NAVIGATION_BAR_TRANSIENT;
-        if ((vis & View.NAVIGATION_BAR_TRANSIENT) != 0) {
+    @Override
+    public void abortTransient(int displayId, @InternalInsetType int[] types) {
+        if (displayId != mDisplayId) {
+            return;
+        }
+        if (!containsType(types, TYPE_NAVIGATION_BAR)) {
+            return;
+        }
+        clearTransient();
+    }
+
+    void clearTransient() {
+        if (mTransientShown) {
+            mTransientShown = false;
+            handleTransientChanged();
+        }
+    }
+
+    private void handleTransientChanged() {
+        if (getView() == null) {
+            return;
+        }
+        if (mNavigationBarView != null) {
+            mNavigationBarView.onTransientStateChanged(mTransientShown);
+        }
+        final int barMode = barMode(mTransientShown, mAppearance);
+        if (updateBarMode(barMode)) {
+            mLightBarController.onNavigationBarModeChanged(barMode);
+        }
+    }
+
+    // Returns true if the bar mode is changed.
+    private boolean updateBarMode(int barMode) {
+        if (mNavigationBarMode != barMode) {
+            if (mNavigationBarMode == MODE_TRANSPARENT
+                    || mNavigationBarMode == MODE_LIGHTS_OUT_TRANSPARENT) {
+                mNavigationBarView.hideRecentsOnboarding();
+            }
+            mNavigationBarMode = barMode;
+            checkNavBarModes();
+            mAutoHideController.touchAutoHide();
+            return true;
+        }
+        return false;
+    }
+
+    private static @TransitionMode int barMode(boolean isTransient, int appearance) {
+        final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_SIDE_BARS;
+        if (isTransient) {
             return MODE_SEMI_TRANSPARENT;
-        } else if ((vis & View.NAVIGATION_BAR_TRANSLUCENT) != 0) {
-            return MODE_TRANSLUCENT;
-        } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
-            return MODE_LIGHTS_OUT_TRANSPARENT;
-        } else if ((vis & View.NAVIGATION_BAR_TRANSPARENT) != 0) {
-            return MODE_TRANSPARENT;
-        } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+        } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
             return MODE_LIGHTS_OUT;
-        } else {
+        } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+            return MODE_LIGHTS_OUT_TRANSPARENT;
+        } else if ((appearance & APPEARANCE_OPAQUE_SIDE_BARS) != 0) {
             return MODE_OPAQUE;
+        } else {
+            return MODE_TRANSPARENT;
         }
     }
 
@@ -990,8 +1028,8 @@
         mAutoHideController.setNavigationBar(this);
     }
 
-    public boolean isSemiTransparent() {
-        return mNavigationBarMode == MODE_SEMI_TRANSPARENT;
+    boolean isTransientShown() {
+        return mTransientShown;
     }
 
     private void checkBarModes() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index ae18833..4b4a35b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -366,8 +366,8 @@
         return super.onTouchEvent(event);
     }
 
-    void onSystemUiVisibilityChanged(int systemUiVisibility) {
-        mEdgeBackGestureHandler.onSystemUiVisibilityChanged(systemUiVisibility);
+    void onTransientStateChanged(boolean isTransient) {
+        mEdgeBackGestureHandler.onNavBarTransientStateChanged(isTransient);
     }
 
     void onBarTransition(int newMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index 4d69f77e..2798285 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -105,7 +105,7 @@
      * @return true if the entry was transferred to and should inflate + alert
      */
     public boolean isAlertTransferPending(@NonNull NotificationEntry entry) {
-        PendingAlertInfo alertInfo = mPendingAlerts.get(entry.key);
+        PendingAlertInfo alertInfo = mPendingAlerts.get(entry.getKey());
         return alertInfo != null && alertInfo.isStillValid();
     }
 
@@ -141,7 +141,7 @@
         @Override
         public void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {
             if (suppressed) {
-                if (mHeadsUpManager.isAlerting(group.summary.key)) {
+                if (mHeadsUpManager.isAlerting(group.summary.getKey())) {
                     handleSuppressedSummaryAlerted(group.summary, mHeadsUpManager);
                 }
             } else {
@@ -151,11 +151,11 @@
                     return;
                 }
                 GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(mGroupManager.getGroupKey(
-                        group.summary.notification));
+                        group.summary.getSbn()));
                 // Group is no longer suppressed. We should check if we need to transfer the alert
                 // back to the summary now that it's no longer suppressed.
                 if (groupAlertEntry.mAlertSummaryOnNextAddition) {
-                    if (!mHeadsUpManager.isAlerting(group.summary.key)) {
+                    if (!mHeadsUpManager.isAlerting(group.summary.getKey())) {
                         alertNotificationWhenPossible(group.summary, mHeadsUpManager);
                     }
                     groupAlertEntry.mAlertSummaryOnNextAddition = false;
@@ -173,7 +173,7 @@
 
     private void onAlertStateChanged(NotificationEntry entry, boolean isAlerting,
             AlertingNotificationManager alertManager) {
-        if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.notification)) {
+        if (isAlerting && mGroupManager.isSummaryOfSuppressedGroup(entry.getSbn())) {
             handleSuppressedSummaryAlerted(entry, alertManager);
         }
     }
@@ -184,7 +184,7 @@
         // see as early as we can if we need to abort a transfer.
         @Override
         public void onPendingEntryAdded(NotificationEntry entry) {
-            String groupKey = mGroupManager.getGroupKey(entry.notification);
+            String groupKey = mGroupManager.getGroupKey(entry.getSbn());
             GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey);
             if (groupAlertEntry != null) {
                 checkShouldTransferBack(groupAlertEntry);
@@ -195,7 +195,7 @@
         // then show the alert.
         @Override
         public void onEntryReinflated(NotificationEntry entry) {
-            PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.key);
+            PendingAlertInfo alertInfo = mPendingAlerts.remove(entry.getKey());
             if (alertInfo != null) {
                 if (alertInfo.isStillValid()) {
                     alertNotificationWhenPossible(entry, mHeadsUpManager);
@@ -214,7 +214,7 @@
             // Removes any alerts pending on this entry. Note that this will not stop any inflation
             // tasks started by a transfer, so this should only be used as clean-up for when
             // inflation is stopped and the pending alert no longer needs to happen.
-            mPendingAlerts.remove(entry.key);
+            mPendingAlerts.remove(entry.getKey());
         }
     };
 
@@ -267,10 +267,10 @@
      */
     private boolean isPendingNotificationInGroup(@NonNull NotificationEntry entry,
             @NonNull NotificationGroup group) {
-        String groupKey = mGroupManager.getGroupKey(group.summary.notification);
-        return mGroupManager.isGroupChild(entry.notification)
-                && Objects.equals(mGroupManager.getGroupKey(entry.notification), groupKey)
-                && !group.children.containsKey(entry.key);
+        String groupKey = mGroupManager.getGroupKey(group.summary.getSbn());
+        return mGroupManager.isGroupChild(entry.getSbn())
+                && Objects.equals(mGroupManager.getGroupKey(entry.getSbn()), groupKey)
+                && !group.children.containsKey(entry.getKey());
     }
 
     /**
@@ -284,10 +284,10 @@
      */
     private void handleSuppressedSummaryAlerted(@NonNull NotificationEntry summary,
             @NonNull AlertingNotificationManager alertManager) {
-        StatusBarNotification sbn = summary.notification;
+        StatusBarNotification sbn = summary.getSbn();
         GroupAlertEntry groupAlertEntry =
                 mGroupAlertEntries.get(mGroupManager.getGroupKey(sbn));
-        if (!mGroupManager.isSummaryOfSuppressedGroup(summary.notification)
+        if (!mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn())
                 || !alertManager.isAlerting(sbn.getKey())
                 || groupAlertEntry == null) {
             return;
@@ -298,7 +298,8 @@
             return;
         }
 
-        NotificationEntry child = mGroupManager.getLogicalChildren(summary.notification).iterator().next();
+        NotificationEntry child =
+                mGroupManager.getLogicalChildren(summary.getSbn()).iterator().next();
         if (child != null) {
             if (child.getRow().keepInParent()
                     || child.isRowRemoved()
@@ -306,7 +307,7 @@
                 // The notification is actually already removed. No need to alert it.
                 return;
             }
-            if (!alertManager.isAlerting(child.key) && onlySummaryAlerts(summary)) {
+            if (!alertManager.isAlerting(child.getKey()) && onlySummaryAlerts(summary)) {
                 groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime();
             }
             transferAlertState(summary, child, alertManager);
@@ -324,7 +325,7 @@
      */
     private void transferAlertState(@NonNull NotificationEntry fromEntry, @NonNull NotificationEntry toEntry,
             @NonNull AlertingNotificationManager alertManager) {
-        alertManager.removeNotification(fromEntry.key, true /* releaseImmediately */);
+        alertManager.removeNotification(fromEntry.getKey(), true /* releaseImmediately */);
         alertNotificationWhenPossible(toEntry, alertManager);
     }
 
@@ -347,7 +348,8 @@
             if (!onlySummaryAlerts(summary)) {
                 return;
             }
-            ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren(summary.notification);
+            ArrayList<NotificationEntry> children = mGroupManager.getLogicalChildren(
+                    summary.getSbn());
             int numChildren = children.size();
             int numPendingChildren = getPendingChildrenNotAlerting(groupAlertEntry.mGroup);
             numChildren += numPendingChildren;
@@ -357,17 +359,18 @@
             boolean releasedChild = false;
             for (int i = 0; i < children.size(); i++) {
                 NotificationEntry entry = children.get(i);
-                if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.key)) {
+                if (onlySummaryAlerts(entry) && mHeadsUpManager.isAlerting(entry.getKey())) {
                     releasedChild = true;
-                    mHeadsUpManager.removeNotification(entry.key, true /* releaseImmediately */);
+                    mHeadsUpManager.removeNotification(
+                            entry.getKey(), true /* releaseImmediately */);
                 }
-                if (mPendingAlerts.containsKey(entry.key)) {
+                if (mPendingAlerts.containsKey(entry.getKey())) {
                     // This is the child that would've been removed if it was inflated.
                     releasedChild = true;
-                    mPendingAlerts.get(entry.key).mAbortOnInflation = true;
+                    mPendingAlerts.get(entry.getKey()).mAbortOnInflation = true;
                 }
             }
-            if (releasedChild && !mHeadsUpManager.isAlerting(summary.key)) {
+            if (releasedChild && !mHeadsUpManager.isAlerting(summary.getKey())) {
                 boolean notifyImmediately = (numChildren - numPendingChildren) > 1;
                 if (notifyImmediately) {
                     alertNotificationWhenPossible(summary, mHeadsUpManager);
@@ -391,20 +394,20 @@
             @NonNull AlertingNotificationManager alertManager) {
         @InflationFlag int contentFlag = alertManager.getContentFlag();
         if (!entry.getRow().isInflationFlagSet(contentFlag)) {
-            mPendingAlerts.put(entry.key, new PendingAlertInfo(entry));
+            mPendingAlerts.put(entry.getKey(), new PendingAlertInfo(entry));
             entry.getRow().updateInflationFlag(contentFlag, true /* shouldInflate */);
             entry.getRow().inflateViews();
             return;
         }
-        if (alertManager.isAlerting(entry.key)) {
-            alertManager.updateNotification(entry.key, true /* alert */);
+        if (alertManager.isAlerting(entry.getKey())) {
+            alertManager.updateNotification(entry.getKey(), true /* alert */);
         } else {
             alertManager.showNotification(entry);
         }
     }
 
     private boolean onlySummaryAlerts(NotificationEntry entry) {
-        return entry.notification.getNotification().getGroupAlertBehavior()
+        return entry.getSbn().getNotification().getGroupAlertBehavior()
                 == Notification.GROUP_ALERT_SUMMARY;
     }
 
@@ -431,7 +434,7 @@
         boolean mAbortOnInflation;
 
         PendingAlertInfo(NotificationEntry entry) {
-            mOriginalNotification = entry.notification;
+            mOriginalNotification = entry.getSbn();
             mEntry = entry;
         }
 
@@ -445,11 +448,11 @@
                 // Notification is aborted due to the transfer being explicitly cancelled
                 return false;
             }
-            if (mEntry.notification.getGroupKey() != mOriginalNotification.getGroupKey()) {
+            if (mEntry.getSbn().getGroupKey() != mOriginalNotification.getGroupKey()) {
                 // Groups have changed
                 return false;
             }
-            if (mEntry.notification.getNotification().isGroupSummary()
+            if (mEntry.getSbn().getNotification().isGroupSummary()
                     != mOriginalNotification.getNotification().isGroupSummary()) {
                 // Notification has changed from group summary to not or vice versa
                 return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index adaea93..e11fc1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -103,8 +103,8 @@
     }
 
     public void onEntryRemoved(NotificationEntry removed) {
-        onEntryRemovedInternal(removed, removed.notification);
-        mIsolatedEntries.remove(removed.key);
+        onEntryRemovedInternal(removed, removed.getSbn());
+        mIsolatedEntries.remove(removed.getKey());
     }
 
     /**
@@ -126,7 +126,7 @@
             return;
         }
         if (isGroupChild(sbn)) {
-            group.children.remove(removed.key);
+            group.children.remove(removed.getKey());
         } else {
             group.summary = null;
         }
@@ -145,7 +145,7 @@
         if (added.isRowRemoved()) {
             added.setDebugThrowable(new Throwable());
         }
-        final StatusBarNotification sbn = added.notification;
+        final StatusBarNotification sbn = added.getSbn();
         boolean isGroupChild = isGroupChild(sbn);
         String groupKey = getGroupKey(sbn);
         NotificationGroup group = mGroupMap.get(groupKey);
@@ -157,17 +157,17 @@
             }
         }
         if (isGroupChild) {
-            NotificationEntry existing = group.children.get(added.key);
+            NotificationEntry existing = group.children.get(added.getKey());
             if (existing != null && existing != added) {
                 Throwable existingThrowable = existing.getDebugThrowable();
-                Log.wtf(TAG, "Inconsistent entries found with the same key " + added.key
+                Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey()
                         + "existing removed: " + existing.isRowRemoved()
                         + (existingThrowable != null
                                 ? Log.getStackTraceString(existingThrowable) + "\n": "")
                         + " added removed" + added.isRowRemoved()
                         , new Throwable());
             }
-            group.children.put(added.key, added);
+            group.children.put(added.getKey(), added);
             updateSuppression(group);
         } else {
             group.summary = added;
@@ -210,7 +210,7 @@
         group.suppressed = group.summary != null && !group.expanded
                 && (childCount == 1
                 || (childCount == 0
-                        && group.summary.notification.getNotification().isGroupSummary()
+                        && group.summary.getSbn().getNotification().isGroupSummary()
                         && (hasIsolatedChildren(group) || hasBubbles)));
         if (prevSuppressed != group.suppressed) {
             for (OnGroupChangeListener listener : mListeners) {
@@ -223,7 +223,7 @@
     }
 
     private boolean hasIsolatedChildren(NotificationGroup group) {
-        return getNumberOfIsolatedChildren(group.summary.notification.getGroupKey()) != 0;
+        return getNumberOfIsolatedChildren(group.summary.getSbn().getGroupKey()) != 0;
     }
 
     private int getNumberOfIsolatedChildren(String groupKey) {
@@ -248,18 +248,18 @@
     public void onEntryUpdated(NotificationEntry entry,
             StatusBarNotification oldNotification) {
         String oldKey = oldNotification.getGroupKey();
-        String newKey = entry.notification.getGroupKey();
+        String newKey = entry.getSbn().getGroupKey();
         boolean groupKeysChanged = !oldKey.equals(newKey);
         boolean wasGroupChild = isGroupChild(oldNotification);
-        boolean isGroupChild = isGroupChild(entry.notification);
+        boolean isGroupChild = isGroupChild(entry.getSbn());
         mIsUpdatingUnchangedGroup = !groupKeysChanged && wasGroupChild == isGroupChild;
         if (mGroupMap.get(getGroupKey(oldNotification)) != null) {
             onEntryRemovedInternal(entry, oldNotification);
         }
         onEntryAdded(entry);
         mIsUpdatingUnchangedGroup = false;
-        if (isIsolated(entry.notification)) {
-            mIsolatedEntries.put(entry.key, entry.notification);
+        if (isIsolated(entry.getSbn())) {
+            mIsolatedEntries.put(entry.getKey(), entry.getSbn());
             if (groupKeysChanged) {
                 updateSuppression(mGroupMap.get(oldKey));
                 updateSuppression(mGroupMap.get(newKey));
@@ -284,7 +284,7 @@
         }
         NotificationEntry logicalGroupSummary = getLogicalGroupSummary(sbn);
         return logicalGroupSummary != null
-                && !logicalGroupSummary.notification.equals(sbn);
+                && !logicalGroupSummary.getSbn().equals(sbn);
     }
 
     private int getTotalNumberOfChildren(StatusBarNotification sbn) {
@@ -351,7 +351,7 @@
         if (group == null || group.summary == null) {
             return false;
         }
-        return !group.children.isEmpty() && Objects.equals(group.summary.notification, sbn);
+        return !group.children.isEmpty() && Objects.equals(group.summary.getSbn(), sbn);
     }
 
     /**
@@ -404,7 +404,7 @@
      * will update the suppression of that group.
      */
     public void updateSuppression(NotificationEntry entry) {
-        NotificationGroup group = mGroupMap.get(getGroupKey(entry.notification));
+        NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn()));
         if (group != null) {
             updateSuppression(group);
         }
@@ -489,12 +489,12 @@
      */
 
     private boolean shouldIsolate(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
         NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
         if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
             return false;
         }
-        if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.key)) {
+        if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) {
             return false;
         }
         return (sbn.getNotification().fullScreenIntent != null
@@ -509,10 +509,10 @@
      * @param entry the notification to isolate
      */
     private void isolateNotification(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
 
         // We will be isolated now, so lets update the groups
-        onEntryRemovedInternal(entry, entry.notification);
+        onEntryRemovedInternal(entry, entry.getSbn());
 
         mIsolatedEntries.put(sbn.getKey(), sbn);
 
@@ -521,7 +521,7 @@
         // even before the groupManager knows about the notification at all.
         // When the notification gets added afterwards it is already isolated and therefore
         // it doesn't lead to an update.
-        updateSuppression(mGroupMap.get(entry.notification.getGroupKey()));
+        updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey()));
         for (OnGroupChangeListener listener : mListeners) {
             listener.onGroupsChanged();
         }
@@ -533,10 +533,10 @@
      * @param entry the notification to un-isolate
      */
     private void stopIsolatingNotification(NotificationEntry entry) {
-        StatusBarNotification sbn = entry.notification;
+        StatusBarNotification sbn = entry.getSbn();
         if (mIsolatedEntries.containsKey(sbn.getKey())) {
             // not isolated anymore, we need to update the groups
-            onEntryRemovedInternal(entry, entry.notification);
+            onEntryRemovedInternal(entry, entry.getSbn());
             mIsolatedEntries.remove(sbn.getKey());
             onEntryAdded(entry);
             for (OnGroupChangeListener listener : mListeners) {
@@ -584,13 +584,13 @@
         @Override
         public String toString() {
             String result = "    summary:\n      "
-                    + (summary != null ? summary.notification : "null")
+                    + (summary != null ? summary.getSbn() : "null")
                     + (summary != null && summary.getDebugThrowable() != null
                             ? Log.getStackTraceString(summary.getDebugThrowable())
                             : "");
             result += "\n    children size: " + children.size();
             for (NotificationEntry child : children.values()) {
-                result += "\n      " + child.notification
+                result += "\n      " + child.getSbn()
                 + (child.getDebugThrowable() != null
                         ? Log.getStackTraceString(child.getDebugThrowable())
                         : "");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 1a37520..1e10b6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -247,10 +247,10 @@
         if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
             return false;
         }
-        if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
+        if (mEntryManager.getNotificationData().isAmbient(entry.getKey()) && !showAmbient) {
             return false;
         }
-        if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
+        if (hideCurrentMedia && entry.getKey().equals(mMediaManager.getMediaNotificationKey())) {
             return false;
         }
         if (!entry.isTopLevelChild()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 89051cd..e00cfb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -55,7 +55,6 @@
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
-import android.widget.LinearLayout;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -243,7 +242,7 @@
     private View mQsNavbarScrim;
     protected NotificationsQuickSettingsContainer mNotificationContainerParent;
     protected NotificationStackScrollLayout mNotificationStackScroller;
-    protected LinearLayout mHomeControlsLayout;
+    protected FrameLayout mHomeControlsLayout;
     private boolean mAnimateNextPositionUpdate;
 
     private int mTrackingPointer;
@@ -770,6 +769,11 @@
         int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
         int topMargin =
                 res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height);
+        int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
+        if (flag == 1) {
+            topMargin = res.getDimensionPixelOffset(
+                    com.android.internal.R.dimen.quick_qs_total_height_with_media);
+        }
         lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
         if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
                 || lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index e7d896c..35039a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -21,7 +21,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.IntDef;
 import android.app.AlarmManager;
-import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
@@ -42,10 +42,10 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.DejankUtils;
-import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.MainResources;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.notification.stack.ViewState;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -59,10 +59,14 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.function.Consumer;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 /**
  * Controls both the scrim behind the notifications and in front of the notifications (when a
  * security method gets shown).
  */
+@Singleton
 public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnColorsChangedListener,
         Dumpable {
 
@@ -124,11 +128,10 @@
     private static final float NOT_INITIALIZED = -1;
 
     private ScrimState mState = ScrimState.UNINITIALIZED;
-    private final Context mContext;
 
-    protected final ScrimView mScrimInFront;
-    protected final ScrimView mScrimBehind;
-    protected final ScrimView mScrimForBubble;
+    private ScrimView mScrimInFront;
+    private ScrimView mScrimBehind;
+    private ScrimView mScrimForBubble;
 
     private final KeyguardStateController mKeyguardStateController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -141,22 +144,21 @@
     private GradientColors mColors;
     private boolean mNeedsDrawableColorUpdate;
 
-    protected float mScrimBehindAlpha;
-    protected float mScrimBehindAlphaResValue;
-    protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
+    private float mScrimBehindAlpha;
+    private float mScrimBehindAlphaResValue;
+    private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
 
     // Assuming the shade is expanded during initialization
     private float mExpansionFraction = 1f;
 
     private boolean mDarkenWhileDragging;
     private boolean mExpansionAffectsAlpha = true;
-    protected boolean mAnimateChange;
+    private boolean mAnimateChange;
     private boolean mUpdatePending;
     private boolean mTracking;
-    protected long mAnimationDuration = -1;
+    private long mAnimationDuration = -1;
     private long mAnimationDelay;
-    private Runnable mOnAnimationFinished;
-    private boolean mDeferFinishedListener;
+    private Animator.AnimatorListener mAnimatorListener;
     private final Interpolator mInterpolator = new DecelerateInterpolator();
 
     private float mInFrontAlpha = NOT_INITIALIZED;
@@ -170,7 +172,7 @@
     private boolean mWallpaperVisibilityTimedOut;
     private int mScrimsVisibility;
     private final TriConsumer<ScrimState, Float, GradientColors> mScrimStateListener;
-    private final Consumer<Integer> mScrimVisibleListener;
+    private Consumer<Integer> mScrimVisibleListener;
     private boolean mBlankScreen;
     private boolean mScreenBlankingCallbackCalled;
     private Callback mCallback;
@@ -185,28 +187,24 @@
     private boolean mWakeLockHeld;
     private boolean mKeyguardOccluded;
 
-    public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble,
-            TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
-            Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
-            AlarmManager alarmManager, KeyguardStateController keyguardStateController) {
-        mScrimBehind = scrimBehind;
-        mScrimInFront = scrimInFront;
-        mScrimForBubble = scrimForBubble;
+    @Inject
+    public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters,
+            AlarmManager alarmManager, KeyguardStateController keyguardStateController,
+            @MainResources Resources resources,
+            DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
+            KeyguardUpdateMonitor keyguardUpdateMonitor, SysuiColorExtractor sysuiColorExtractor) {
 
-        mScrimStateListener = scrimStateListener;
-        mScrimVisibleListener = scrimVisibleListener;
+        mScrimStateListener = lightBarController::setScrimState;
 
-        mContext = scrimBehind.getContext();
         mKeyguardStateController = keyguardStateController;
         mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
-        mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
-        mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
-        mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha);
-        mHandler = getHandler();
+        mScrimBehindAlphaResValue = resources.getFloat(R.dimen.scrim_behind_alpha);
+        mHandler = handler;
         mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout,
                 "hide_aod_wallpaper", mHandler);
-        mWakeLock = createWakeLock();
+        mWakeLock = delayedWakeLockBuilder.setHandler(mHandler).setTag("Scrims").build();
         // Scrim alpha is initially set to the value on the resource but might be changed
         // to make sure that text on top of it is legible.
         mScrimBehindAlpha = mScrimBehindAlphaResValue;
@@ -219,10 +217,20 @@
             }
         });
 
-        mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+        mColorExtractor = sysuiColorExtractor;
         mColorExtractor.addOnColorsChangedListener(this);
         mColors = mColorExtractor.getNeutralColors();
         mNeedsDrawableColorUpdate = true;
+    }
+
+    /**
+     * Attach the controller to the supplied views.
+     */
+    public void attachViews(
+            ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble) {
+        mScrimBehind = scrimBehind;
+        mScrimInFront = scrimInFront;
+        mScrimForBubble = scrimForBubble;
 
         final ScrimState[] states = ScrimState.values();
         for (int i = 0; i < states.length; i++) {
@@ -233,8 +241,12 @@
         mScrimBehind.setDefaultFocusHighlightEnabled(false);
         mScrimInFront.setDefaultFocusHighlightEnabled(false);
         mScrimForBubble.setDefaultFocusHighlightEnabled(false);
-
         updateScrims();
+        mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
+    }
+
+    void setScrimVisibleListener(Consumer<Integer> listener) {
+        mScrimVisibleListener = listener;
     }
 
     public void transitionTo(ScrimState state) {
@@ -658,6 +670,9 @@
 
     private void startScrimAnimation(final View scrim, float current) {
         ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+        if (mAnimatorListener != null) {
+            anim.addListener(mAnimatorListener);
+        }
         final int initialScrimTint = scrim instanceof ScrimView ? ((ScrimView) scrim).getTint() :
                 Color.TRANSPARENT;
         anim.addUpdateListener(animation -> {
@@ -683,11 +698,6 @@
                 onFinished(lastCallback);
 
                 dispatchScrimsVisible();
-
-                if (!mDeferFinishedListener && mOnAnimationFinished != null) {
-                    mOnAnimationFinished.run();
-                    mOnAnimationFinished = null;
-                }
             }
         });
 
@@ -732,11 +742,6 @@
             mCallback.onStart();
         }
         updateScrims();
-        if (mOnAnimationFinished != null && !isAnimating(mScrimInFront)
-                && !isAnimating(mScrimBehind)) {
-            mOnAnimationFinished.run();
-            mOnAnimationFinished = null;
-        }
         return true;
     }
 
@@ -785,8 +790,8 @@
     }
 
     @VisibleForTesting
-    void setOnAnimationFinished(Runnable onAnimationFinished) {
-        mOnAnimationFinished = onAnimationFinished;
+    void setAnimatorListener(Animator.AnimatorListener animatorListener) {
+        mAnimatorListener = animatorListener;
     }
 
     private void updateScrim(ScrimView scrim, float alpha) {
@@ -794,16 +799,11 @@
 
         ValueAnimator previousAnimator = ViewState.getChildTag(scrim, TAG_KEY_ANIM);
         if (previousAnimator != null) {
-            if (mAnimateChange) {
-                // We are not done yet! Defer calling the finished listener.
-                mDeferFinishedListener = true;
-            }
             // Previous animators should always be cancelled. Not doing so would cause
             // overlap, especially on states that don't animate, leading to flickering,
             // and in the worst case, an internal state that doesn't represent what
             // transitionTo requested.
             cancelAnimator(previousAnimator);
-            mDeferFinishedListener = false;
         }
 
         if (mPendingFrameCallback != null) {
@@ -839,8 +839,7 @@
         }
     }
 
-    @VisibleForTesting
-    protected void cancelAnimator(ValueAnimator previousAnimator) {
+    private void cancelAnimator(ValueAnimator previousAnimator) {
         if (previousAnimator != null) {
             previousAnimator.cancel();
         }
@@ -888,11 +887,6 @@
         mScrimBehind.postOnAnimationDelayed(callback, 32 /* delayMillis */);
     }
 
-    @VisibleForTesting
-    protected Handler getHandler() {
-        return new Handler();
-    }
-
     public int getBackgroundColor() {
         int color = mColors.getMainColor();
         return Color.argb((int) (mScrimBehind.getViewAlpha() * Color.alpha(color)),
@@ -914,11 +908,6 @@
         scheduleUpdate();
     }
 
-    @VisibleForTesting
-    protected WakeLock createWakeLock() {
-        return new DelayedWakeLock(mHandler, WakeLock.createPartial(mContext, "Scrims"));
-    }
-
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println(" ScrimController: ");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index e0597159..13055ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -39,15 +39,20 @@
         @Override
         public void prepare(ScrimState previousState) {
             mFrontTint = Color.BLACK;
-            mBehindTint = previousState.mBehindTint;
+            mBehindTint = Color.BLACK;
             mBubbleTint = previousState.mBubbleTint;
 
             mFrontAlpha = 1f;
-            mBehindAlpha = previousState.mBehindAlpha;
+            mBehindAlpha = 1f;
             mBubbleAlpha = previousState.mBubbleAlpha;
 
             mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
         }
+
+        @Override
+        public boolean isLowPowerState() {
+            return true;
+        }
     },
 
     /**
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 c092f9b..70dca2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -24,6 +24,11 @@
 import static android.app.StatusBarManager.WindowVisibleState;
 import static android.app.StatusBarManager.windowStateToString;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.view.InsetsFlags.getAppearance;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_TOP_BAR;
 
 import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
 import static com.android.systemui.Dependency.BG_HANDLER;
@@ -45,12 +50,10 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
-import android.app.AlarmManager;
 import android.app.AppOpsManager;
 import android.app.IWallpaperManager;
 import android.app.KeyguardManager;
@@ -75,7 +78,6 @@
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.PointF;
-import android.graphics.Rect;
 import android.media.AudioAttributes;
 import android.metrics.LogMaker;
 import android.net.Uri;
@@ -104,6 +106,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.IWindowManager;
+import android.view.InsetsState.InternalInsetType;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -112,6 +115,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.WindowInsetsController.Appearance;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
@@ -124,6 +128,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.RegisterStatusBarResult;
+import com.android.internal.view.AppearanceRegion;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -151,10 +156,8 @@
 import com.android.systemui.charging.WirelessChargingAnimation;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.doze.DozeEvent;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
-import com.android.systemui.doze.DozeReceiver;
 import com.android.systemui.fragments.ExtensionFragmentListener;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -179,6 +182,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyboardShortcuts;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -198,7 +202,7 @@
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 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.NewNotifPipeline;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationClicker;
@@ -246,6 +250,7 @@
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import dagger.Lazy;
 import dagger.Subcomponent;
 
 @Singleton
@@ -339,7 +344,7 @@
     /**
      * The {@link StatusBarState} of the status bar.
      */
-    protected int mState;
+    protected int mState; // TODO: remove this. Just use StatusBarStateController
     protected boolean mBouncerShowing;
 
     private PhoneStatusBarPolicy mIconPolicy;
@@ -348,8 +353,9 @@
     private VolumeComponent mVolumeComponent;
     private BrightnessMirrorController mBrightnessMirrorController;
     private boolean mBrightnessMirrorVisible;
-    protected BiometricUnlockController mBiometricUnlockController;
+    private BiometricUnlockController mBiometricUnlockController;
     private final LightBarController mLightBarController;
+    private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
     protected LockscreenWallpaper mLockscreenWallpaper;
     private final AutoHideController mAutoHideController;
 
@@ -364,12 +370,13 @@
     protected StatusBarWindowController mStatusBarWindowController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @VisibleForTesting
-    DozeServiceHost mDozeServiceHost = new DozeServiceHost();
+    DozeServiceHost mDozeServiceHost;
     private boolean mWakeUpComingFromTouch;
     private PointF mWakeUpTouchLocation;
 
     private final Object mQueueLock = new Object();
 
+    private final FeatureFlags mFeatureFlags;
     private final StatusBarIconController mIconController;
     private final DozeLog mDozeLog;
     private final InjectionInflationController mInjectionInflater;
@@ -381,13 +388,14 @@
     private final DynamicPrivacyController mDynamicPrivacyController;
     private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
     private final boolean mAllowNotificationLongPress;
-    private final NotifPipelineInitializer mNotifPipelineInitializer;
+    private final Lazy<NewNotifPipeline> mNewNotifPipeline;
     private final FalsingManager mFalsingManager;
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final ConfigurationController mConfigurationController;
     private final StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
     private final NotifLog mNotifLog;
     private final DozeParameters mDozeParameters;
+    private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
 
     // expanded notifications
     protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -425,10 +433,13 @@
     private int mDisabled1 = 0;
     private int mDisabled2 = 0;
 
-    // tracking calls to View.setSystemUiVisibility()
-    private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
-    private final Rect mLastFullscreenStackBounds = new Rect();
-    private final Rect mLastDockedStackBounds = new Rect();
+    /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+    private @Appearance int mAppearance;
+
+    private boolean mTransientShown;
+
+    private boolean mAppFullscreen;
+    private boolean mAppImmersive;
 
     private final DisplayMetrics mDisplayMetrics;
 
@@ -474,12 +485,11 @@
     private @TransitionMode int mStatusBarMode;
 
     private ViewMediatorCallback mKeyguardViewMediatorCallback;
-    protected ScrimController mScrimController;
+    private final ScrimController mScrimController;
     protected DozeScrimController mDozeScrimController;
     private final UiOffloadThread mUiOffloadThread;
 
     protected boolean mDozing;
-    private boolean mDozingRequested;
 
     private final NotificationMediaManager mMediaManager;
     private final NotificationLockscreenUserManager mLockscreenUserManager;
@@ -598,7 +608,6 @@
     private ActivityLaunchAnimator mActivityLaunchAnimator;
     protected StatusBarNotificationPresenter mPresenter;
     private NotificationActivityStarter mNotificationActivityStarter;
-    private boolean mPulsing;
     private final BubbleController mBubbleController;
     private final BubbleController.BubbleExpandListener mBubbleExpandListener;
 
@@ -608,7 +617,6 @@
     public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
         Dependency.get(MAIN_HANDLER).post(() -> {
             mForegroundServiceController.onAppOpChanged(code, uid, packageName, active);
-            mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active);
         });
     }
 
@@ -621,6 +629,7 @@
     @Inject
     public StatusBar(
             Context context,
+            FeatureFlags featureFlags,
             LightBarController lightBarController,
             AutoHideController autoHideController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -635,7 +644,7 @@
             DynamicPrivacyController dynamicPrivacyController,
             BypassHeadsUpNotifier bypassHeadsUpNotifier,
             @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
-            NotifPipelineInitializer notifPipelineInitializer,
+            Lazy<NewNotifPipeline> newNotifPipeline,
             FalsingManager falsingManager,
             BroadcastDispatcher broadcastDispatcher,
             RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -675,8 +684,15 @@
             StatusBarWindowController statusBarWindowController,
             StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
             NotifLog notifLog,
-            DozeParameters dozeParameters) {
+            DozeParameters dozeParameters,
+            ScrimController scrimController,
+            Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+            DozeServiceHost dozeServiceHost,
+            PowerManager powerManager,
+            DozeScrimController dozeScrimController) {
         super(context);
+        mFeatureFlags = featureFlags;
         mLightBarController = lightBarController;
         mAutoHideController = autoHideController;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -691,7 +707,7 @@
         mDynamicPrivacyController = dynamicPrivacyController;
         mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
         mAllowNotificationLongPress = allowNotificationLongPress;
-        mNotifPipelineInitializer = notifPipelineInitializer;
+        mNewNotifPipeline = newNotifPipeline;
         mFalsingManager = falsingManager;
         mBroadcastDispatcher = broadcastDispatcher;
         mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
@@ -731,7 +747,13 @@
         mStatusBarWindowController = statusBarWindowController;
         mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder;
         mNotifLog = notifLog;
+        mDozeServiceHost = dozeServiceHost;
+        mPowerManager = powerManager;
         mDozeParameters = dozeParameters;
+        mScrimController = scrimController;
+        mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
+        mDozeScrimController = dozeScrimController;
+        mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
 
         mBubbleExpandListener =
                 (isExpanding, key) -> {
@@ -783,7 +805,6 @@
         mAccessibilityManager = (AccessibilityManager)
                 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
 
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -821,10 +842,22 @@
         // Set up the initial notification state. This needs to happen before CommandQueue.disable()
         setUpPresenter();
 
-        setSystemUiVisibility(mDisplayId, result.mSystemUiVisibility,
-                result.mFullscreenStackSysUiVisibility, result.mDockedStackSysUiVisibility,
-                0xffffffff, result.mFullscreenStackBounds, result.mDockedStackBounds,
-                result.mNavbarColorManagedByIme);
+        if ((result.mSystemUiVisibility & View.STATUS_BAR_TRANSIENT) != 0) {
+            showTransientUnchecked();
+        }
+        final int fullscreenAppearance = getAppearance(result.mFullscreenStackSysUiVisibility);
+        final int dockedAppearance = getAppearance(result.mDockedStackSysUiVisibility);
+        final AppearanceRegion[] appearanceRegions = result.mDockedStackBounds.isEmpty()
+                ? new AppearanceRegion[]{
+                        new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds)}
+                : new AppearanceRegion[]{
+                        new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds),
+                        new AppearanceRegion(dockedAppearance, result.mDockedStackBounds)};
+        onSystemBarAppearanceChanged(mDisplayId, getAppearance(result.mSystemUiVisibility),
+                appearanceRegions, result.mNavbarColorManagedByIme);
+        mAppFullscreen = result.mAppFullscreen;
+        mAppImmersive = result.mAppImmersive;
+
         // StatusBarManagerService has a back up of IME token and it's restored here.
         setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
                 result.mImeBackDisposition, result.mShowImeSwitcher);
@@ -871,6 +904,9 @@
         startKeyguard();
 
         mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
+        mDozeServiceHost.initialize(this, mNotificationIconAreaController,
+                mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager,
+                mNotificationPanel, mAmbientIndicationContainer);
         putComponent(DozeHost.class, mDozeServiceHost);
 
         mScreenPinningRequest = new ScreenPinningRequest(mContext);
@@ -990,7 +1026,8 @@
         createNavigationBar(result);
 
         if (ENABLE_LOCKSCREEN_WALLPAPER) {
-            mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
+            mLockscreenWallpaper = mLockscreenWallpaperLazy.get();
+            mLockscreenWallpaper.setHandler(mHandler);
         }
 
         mKeyguardIndicationController =
@@ -1024,22 +1061,16 @@
         ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front);
         ScrimView scrimForBubble = mStatusBarWindow.findViewById(R.id.scrim_for_bubble);
 
-        mScrimController = SystemUIFactory.getInstance().createScrimController(
-                scrimBehind, scrimInFront, scrimForBubble, mLockscreenWallpaper,
-                (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color),
-                scrimsVisible -> {
-                    if (mStatusBarWindowController != null) {
-                        mStatusBarWindowController.setScrimsVisibility(scrimsVisible);
-                    }
-                    if (mStatusBarWindow != null) {
-                        mStatusBarWindowViewController.onScrimVisibilityChanged(scrimsVisible);
-                    }
-                }, mDozeParameters,
-                mContext.getSystemService(AlarmManager.class),
-                mKeyguardStateController);
+        mScrimController.setScrimVisibleListener(scrimsVisible -> {
+            mStatusBarWindowController.setScrimsVisibility(scrimsVisible);
+            if (mStatusBarWindow != null) {
+                mStatusBarWindowViewController.onScrimVisibilityChanged(scrimsVisible);
+            }
+        });
+        mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble);
+
         mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
                 mHeadsUpManager, mNotificationIconAreaController, mScrimController);
-        mDozeScrimController = new DozeScrimController(mDozeParameters, mDozeLog);
 
         BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop);
         mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
@@ -1211,7 +1242,9 @@
         mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);
         mNotificationListController.bind();
 
-        mNotifPipelineInitializer.initialize(mNotificationListener);
+        if (mFeatureFlags.isNewNotifPipelineEnabled()) {
+            mNewNotifPipeline.get().initialize(mNotificationListener);
+        }
     }
 
     /**
@@ -1341,11 +1374,7 @@
 
     protected void startKeyguard() {
         Trace.beginSection("StatusBar#startKeyguard");
-        mBiometricUnlockController = new BiometricUnlockController(mContext,
-                mDozeScrimController, mKeyguardViewMediator,
-                mScrimController, this, mKeyguardStateController, new Handler(),
-                mKeyguardUpdateMonitor, mKeyguardBypassController, mDozeParameters);
-        putComponent(BiometricUnlockController.class, mBiometricUnlockController);
+        mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
         mStatusBarKeyguardViewManager = mKeyguardViewMediator.registerStatusBar(this,
                 getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
                 mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
@@ -1702,7 +1731,7 @@
         if (isDozing() && isHeadsUp) {
             entry.setPulseSuppressed(false);
             mDozeServiceHost.fireNotificationPulse(entry);
-            if (mPulsing) {
+            if (mDozeServiceHost.isPulsing()) {
                 mDozeScrimController.cancelPendingPulseTimeout();
             }
         }
@@ -1734,7 +1763,7 @@
     }
 
     public boolean isPulsing() {
-        return mPulsing;
+        return mDozeServiceHost.isPulsing();
     }
 
     public boolean hideStatusBarIconsWhenExpanded() {
@@ -1888,7 +1917,7 @@
 
     public void maybeEscalateHeadsUp() {
         mHeadsUpManager.getAllEntries().forEach(entry -> {
-            final StatusBarNotification sbn = entry.notification;
+            final StatusBarNotification sbn = entry.getSbn();
             final Notification notification = sbn.getNotification();
             if (notification.fullScreenIntent != null) {
                 if (DEBUG) {
@@ -2223,49 +2252,104 @@
         }
     }
 
-    @Override // CommandQueue
-    public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
-            int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
-            boolean navbarColorManagedByIme) {
+    @Override
+    public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+            AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
         if (displayId != mDisplayId) {
             return;
         }
-        final int oldVal = mSystemUiVisibility;
-        final int newVal = (oldVal&~mask) | (vis&mask);
-        final int diff = newVal ^ oldVal;
-        if (DEBUG) Log.d(TAG, String.format(
-                "setSystemUiVisibility displayId=%d vis=%s mask=%s oldVal=%s newVal=%s diff=%s",
-                displayId, Integer.toHexString(vis), Integer.toHexString(mask),
-                Integer.toHexString(oldVal), Integer.toHexString(newVal),
-                Integer.toHexString(diff)));
-        boolean sbModeChanged = false;
-        if (diff != 0) {
-            mSystemUiVisibility = newVal;
+        boolean barModeChanged = false;
+        final int diff = mAppearance ^ appearance;
+        if (mAppearance != appearance) {
+            mAppearance = appearance;
 
             // update low profile
-            if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+            if ((diff & APPEARANCE_LOW_PROFILE_BARS) != 0) {
                 updateAreThereNotifications();
             }
-
-            // ready to unhide
-            if ((vis & View.STATUS_BAR_UNHIDE) != 0) {
-                mNoAnimationOnNextBarModeChange = true;
-            }
-
-            // update status bar mode
-            final int sbMode = computeStatusBarMode(oldVal, newVal);
-
-            sbModeChanged = sbMode != -1;
-            if (sbModeChanged && sbMode != mStatusBarMode) {
-                mStatusBarMode = sbMode;
-                checkBarModes();
-                mAutoHideController.touchAutoHide();
-            }
-            mStatusBarStateController.setSystemUiVisibility(mSystemUiVisibility);
+            barModeChanged = updateBarMode(barMode(mTransientShown, appearance));
         }
-        mLightBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
-                mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode,
-                navbarColorManagedByIme);
+        mLightBarController.onStatusBarAppearanceChanged(appearanceRegions, barModeChanged,
+                mStatusBarMode, navbarColorManagedByIme);
+    }
+
+    @Override
+    public void showTransient(int displayId, @InternalInsetType int[] types) {
+        if (displayId != mDisplayId) {
+            return;
+        }
+        if (!containsType(types, TYPE_TOP_BAR)) {
+            return;
+        }
+        showTransientUnchecked();
+    }
+
+    private void showTransientUnchecked() {
+        if (!mTransientShown) {
+            mTransientShown = true;
+            mNoAnimationOnNextBarModeChange = true;
+            handleTransientChanged();
+        }
+    }
+
+    @Override
+    public void abortTransient(int displayId, @InternalInsetType int[] types) {
+        if (displayId != mDisplayId) {
+            return;
+        }
+        if (!containsType(types, TYPE_TOP_BAR)) {
+            return;
+        }
+        clearTransient();
+    }
+
+    void clearTransient() {
+        if (mTransientShown) {
+            mTransientShown = false;
+            handleTransientChanged();
+        }
+    }
+
+    private void handleTransientChanged() {
+        final int barMode = barMode(mTransientShown, mAppearance);
+        if (updateBarMode(barMode)) {
+            mLightBarController.onStatusBarModeChanged(barMode);
+        }
+    }
+
+    private boolean updateBarMode(int barMode) {
+        if (mStatusBarMode != barMode) {
+            mStatusBarMode = barMode;
+            checkBarModes();
+            mAutoHideController.touchAutoHide();
+            return true;
+        }
+        return false;
+    }
+
+    private static @TransitionMode int barMode(boolean isTransient, int appearance) {
+        final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_TOP_BAR;
+        if (isTransient) {
+            return MODE_SEMI_TRANSPARENT;
+        } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
+            return MODE_LIGHTS_OUT;
+        } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+            return MODE_LIGHTS_OUT_TRANSPARENT;
+        } else if ((appearance & APPEARANCE_OPAQUE_TOP_BAR) != 0) {
+            return MODE_OPAQUE;
+        } else {
+            return MODE_TRANSPARENT;
+        }
+    }
+
+    @Override
+    public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+        if (displayId != mDisplayId) {
+            return;
+        }
+        mAppFullscreen = isFullscreen;
+        mAppImmersive = isImmersive;
+        mStatusBarStateController.setFullscreenState(isFullscreen, isImmersive);
     }
 
     @Override
@@ -2296,40 +2380,10 @@
         setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, running);
     }
 
-    protected @TransitionMode int computeStatusBarMode(int oldVal, int newVal) {
-        return computeBarMode(oldVal, newVal);
-    }
-
     protected BarTransitions getStatusBarTransitions() {
         return mStatusBarView.getBarTransitions();
     }
 
-    protected @TransitionMode int computeBarMode(int oldVis, int newVis) {
-        final int oldMode = barMode(oldVis);
-        final int newMode = barMode(newVis);
-        if (oldMode == newMode) {
-            return -1; // no mode change
-        }
-        return newMode;
-    }
-
-    private @TransitionMode int barMode(int vis) {
-        int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.STATUS_BAR_TRANSPARENT;
-        if ((vis & View.STATUS_BAR_TRANSIENT) != 0) {
-            return MODE_SEMI_TRANSPARENT;
-        } else if ((vis & View.STATUS_BAR_TRANSLUCENT) != 0) {
-            return MODE_TRANSLUCENT;
-        } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
-            return MODE_LIGHTS_OUT_TRANSPARENT;
-        } else if ((vis & View.STATUS_BAR_TRANSPARENT) != 0) {
-            return MODE_TRANSPARENT;
-        } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
-            return MODE_LIGHTS_OUT;
-        } else {
-            return MODE_OPAQUE;
-        }
-    }
-
     void checkBarModes() {
         if (mDemoMode) return;
         if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
@@ -2385,20 +2439,16 @@
 
     /** Returns whether the top activity is in fullscreen mode. */
     public boolean inFullscreenMode() {
-        return 0
-                != (mSystemUiVisibility
-                        & (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION));
+        return mAppFullscreen;
     }
 
     /** Returns whether the top activity is in immersive mode. */
     public boolean inImmersiveMode() {
-        return 0
-                != (mSystemUiVisibility
-                        & (View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY));
+        return mAppImmersive;
     }
 
     private boolean areLightsOn() {
-        return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
+        return 0 == (mAppearance & APPEARANCE_LOW_PROFILE_BARS);
     }
 
     public static String viewInfo(View v) {
@@ -2776,7 +2826,7 @@
         if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
                 && mKeyguardStateController.canDismissLockScreen()
                 && !mStatusBarStateController.leaveOpenOnKeyguardHide()
-                && isPulsing()) {
+                && mDozeServiceHost.isPulsing()) {
             // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
             // TODO: Factor this transition out of BiometricUnlockController.
             mBiometricUnlockController.startWakeAndUnlock(
@@ -3107,7 +3157,7 @@
         return mState == StatusBarState.FULLSCREEN_USER_SWITCHER;
     }
 
-    private boolean updateIsKeyguard() {
+    boolean updateIsKeyguard() {
         boolean wakeAndUnlocking = mBiometricUnlockController.getMode()
                 == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
 
@@ -3115,8 +3165,8 @@
         // there's no surface we can show to the user. Note that the device goes fully interactive
         // late in the transition, so we also allow the device to start dozing once the screen has
         // turned off fully.
-        boolean keyguardForDozing = mDozingRequested &&
-                (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
+        boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
+                && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
         boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
                 || keyguardForDozing) && !wakeAndUnlocking;
         if (keyguardForDozing) {
@@ -3532,7 +3582,7 @@
     public void onStateChanged(int newState) {
         mState = newState;
         updateReportRejectedTouchVisibility();
-        updateDozing();
+        mDozeServiceHost.updateDozing();
         updateTheme();
         mNavigationBarController.touchAutoDim(mDisplayId);
         Trace.beginSection("StatusBar#updateKeyguardState");
@@ -3570,36 +3620,23 @@
     public void onDozingChanged(boolean isDozing) {
         Trace.beginSection("StatusBar#updateDozing");
         mDozing = isDozing;
+        mDozeServiceHost.setDozing(mDozing);
 
         // Collapse the notification panel if open
-        boolean dozingAnimated = mDozingRequested && mDozeParameters.shouldControlScreenOff();
+        boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
+                && mDozeParameters.shouldControlScreenOff();
         mNotificationPanel.resetViews(dozingAnimated);
 
         updateQsExpansionEnabled();
         mKeyguardViewMediator.setDozing(mDozing);
 
         mEntryManager.updateNotifications("onDozingChanged");
-        updateDozingState();
+        mDozeServiceHost.updateDozing();
         updateScrimController();
         updateReportRejectedTouchVisibility();
         Trace.endSection();
     }
 
-    private void updateDozing() {
-        // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
-        boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
-                || mBiometricUnlockController.getMode()
-                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
-        // When in wake-and-unlock we may not have received a change to mState
-        // but we still should not be dozing, manually set to false.
-        if (mBiometricUnlockController.getMode() ==
-                BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
-            dozing = false;
-        }
-
-        mStatusBarStateController.setIsDozing(dozing);
-    }
-
     private void updateKeyguardState() {
         mKeyguardStateController.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
                 mStatusBarKeyguardViewManager.isOccluded());
@@ -3689,9 +3726,7 @@
             // Indicate that the group expansion is changing at this time -- this way the group
             // and children backgrounds / divider animations will look correct.
             entry.setGroupExpansionChanging(true);
-            if (entry.notification != null) {
-                userId = entry.notification.getUserId();
-            }
+            userId = entry.getSbn().getUserId();
         }
         boolean fullShadeNeedsBouncer = !mLockscreenUserManager.
                 userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId())
@@ -3826,10 +3861,11 @@
      * collapse the panel after we expanded it, and thus we would end up with a blank
      * Keyguard.
      */
-    private void updateNotificationPanelTouchState() {
+    void updateNotificationPanelTouchState() {
         boolean goingToSleepWithoutAnimation = isGoingToSleep()
                 && !mDozeParameters.shouldControlScreenOff();
-        boolean disabled = (!mDeviceInteractive && !mPulsing) || goingToSleepWithoutAnimation;
+        boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
+                || goingToSleepWithoutAnimation;
         mNotificationPanel.setTouchAndAnimationDisabled(disabled);
         mNotificationIconAreaController.setAnimationsEnabled(!disabled);
     }
@@ -3979,7 +4015,7 @@
     }
 
     public void notifyBiometricAuthModeChanged() {
-        updateDozing();
+        mDozeServiceHost.updateDozing();
         updateScrimController();
         mStatusBarWindowViewController.onBiometricAuthModeChanged(
                 mBiometricUnlockController.isWakeAndUnlock(),
@@ -4015,7 +4051,7 @@
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         } else if (mBrightnessMirrorVisible) {
             mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
-        } else if (isPulsing()) {
+        } else if (mDozeServiceHost.isPulsing()) {
             mScrimController.transitionTo(ScrimState.PULSING,
                     mDozeScrimController.getScrimCallback());
         } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
@@ -4045,287 +4081,8 @@
         return mStatusBarKeyguardViewManager.isShowing();
     }
 
-    @VisibleForTesting
-    final class DozeServiceHost implements DozeHost {
-        private final ArrayList<Callback> mCallbacks = new ArrayList<>();
-        private boolean mAnimateWakeup;
-        private boolean mAnimateScreenOff;
-        private boolean mIgnoreTouchWhilePulsing;
-        private Runnable mPendingScreenOffCallback;
-        @VisibleForTesting
-        boolean mWakeLockScreenPerformsAuth = SystemProperties.getBoolean(
-                "persist.sysui.wake_performs_auth", true);
-
-        @Override
-        public String toString() {
-            return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
-        }
-
-        public void firePowerSaveChanged(boolean active) {
-            for (Callback callback : mCallbacks) {
-                callback.onPowerSaveChanged(active);
-            }
-        }
-
-        public void fireNotificationPulse(NotificationEntry entry) {
-            Runnable pulseSupressedListener = () -> {
-                entry.setPulseSuppressed(true);
-                mNotificationIconAreaController.updateAodNotificationIcons();
-            };
-            for (Callback callback : mCallbacks) {
-                callback.onNotificationAlerted(pulseSupressedListener);
-            }
-        }
-
-        @Override
-        public void addCallback(@NonNull Callback callback) {
-            mCallbacks.add(callback);
-        }
-
-        @Override
-        public void removeCallback(@NonNull Callback callback) {
-            mCallbacks.remove(callback);
-        }
-
-        @Override
-        public void startDozing() {
-            if (!mDozingRequested) {
-                mDozingRequested = true;
-                mDozeLog.traceDozing(mDozing);
-                updateDozing();
-                updateIsKeyguard();
-            }
-        }
-
-        @Override
-        public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
-            if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) {
-                mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
-                        "com.android.systemui:LONG_PRESS");
-                startAssist(new Bundle());
-                return;
-            }
-
-            if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
-                mScrimController.setWakeLockScreenSensorActive(true);
-            }
-
-            if (reason == DozeEvent.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
-                mStatusBarWindowViewController.suppressWakeUpGesture(true);
-            }
-
-            boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
-                            && mWakeLockScreenPerformsAuth;
-            // Set the state to pulsing, so ScrimController will know what to do once we ask it to
-            // execute the transition. The pulse callback will then be invoked when the scrims
-            // are black, indicating that StatusBar is ready to present the rest of the UI.
-            mPulsing = true;
-            mDozeScrimController.pulse(new PulseCallback() {
-                @Override
-                public void onPulseStarted() {
-                    callback.onPulseStarted();
-                    updateNotificationPanelTouchState();
-                    setPulsing(true);
-                }
-
-                @Override
-                public void onPulseFinished() {
-                    mPulsing = false;
-                    callback.onPulseFinished();
-                    updateNotificationPanelTouchState();
-                    mScrimController.setWakeLockScreenSensorActive(false);
-                    if (mStatusBarWindow != null) {
-                        mStatusBarWindowViewController.suppressWakeUpGesture(false);
-                    }
-                    setPulsing(false);
-                }
-
-                private void setPulsing(boolean pulsing) {
-                    mStatusBarStateController.setPulsing(pulsing);
-                    mStatusBarKeyguardViewManager.setPulsing(pulsing);
-                    mKeyguardViewMediator.setPulsing(pulsing);
-                    mNotificationPanel.setPulsing(pulsing);
-                    mVisualStabilityManager.setPulsing(pulsing);
-                    mStatusBarWindowViewController.setPulsing(pulsing);
-                    mIgnoreTouchWhilePulsing = false;
-                    if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
-                        mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
-                    }
-                    updateScrimController();
-                    mPulseExpansionHandler.setPulsing(pulsing);
-                    mWakeUpCoordinator.setPulsing(pulsing);
-                }
-            }, reason);
-            // DozeScrimController is in pulse state, now let's ask ScrimController to start
-            // pulsing and draw the black frame, if necessary.
-            updateScrimController();
-        }
-
-        @Override
-        public void stopDozing() {
-            if (mDozingRequested) {
-                mDozingRequested = false;
-                mDozeLog.traceDozing(mDozing);
-                updateDozing();
-            }
-        }
-
-        @Override
-        public void onIgnoreTouchWhilePulsing(boolean ignore) {
-            if (ignore != mIgnoreTouchWhilePulsing) {
-                mDozeLog.tracePulseTouchDisabledByProx(ignore);
-            }
-            mIgnoreTouchWhilePulsing = ignore;
-            if (isDozing() && ignore) {
-                mStatusBarWindowViewController.cancelCurrentTouch();
-            }
-        }
-
-        @Override
-        public void dozeTimeTick() {
-            mNotificationPanel.dozeTimeTick();
-            if (mAmbientIndicationContainer instanceof DozeReceiver) {
-                ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
-            }
-        }
-
-        @Override
-        public boolean isPowerSaveActive() {
-            return mBatteryController.isAodPowerSave();
-        }
-
-        @Override
-        public boolean isPulsingBlocked() {
-            return mBiometricUnlockController.getMode()
-                    == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
-        }
-
-        @Override
-        public boolean isProvisioned() {
-            return mDeviceProvisionedController.isDeviceProvisioned()
-                    && mDeviceProvisionedController.isCurrentUserSetup();
-        }
-
-        @Override
-        public boolean isBlockingDoze() {
-            if (mBiometricUnlockController.hasPendingAuthentication()) {
-                Log.i(TAG, "Blocking AOD because fingerprint has authenticated");
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public void extendPulse(int reason) {
-            if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) {
-                mScrimController.setWakeLockScreenSensorActive(true);
-            }
-            if (mDozeScrimController.isPulsing() && mHeadsUpManager.hasNotifications()) {
-                mHeadsUpManager.extendHeadsUp();
-            } else {
-                mDozeScrimController.extendPulse();
-            }
-        }
-
-        @Override
-        public void stopPulsing() {
-            if (mDozeScrimController.isPulsing()) {
-                mDozeScrimController.pulseOutNow();
-            }
-        }
-
-        @Override
-        public void setAnimateWakeup(boolean animateWakeup) {
-            if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
-                    || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) {
-                // Too late to change the wakeup animation.
-                return;
-            }
-            mAnimateWakeup = animateWakeup;
-        }
-
-        @Override
-        public void setAnimateScreenOff(boolean animateScreenOff) {
-            mAnimateScreenOff = animateScreenOff;
-        }
-
-        @Override
-        public void onSlpiTap(float screenX, float screenY) {
-            if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
-                && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
-                mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2);
-                float viewX = screenX - mTmpInt2[0];
-                float viewY = screenY - mTmpInt2[1];
-                if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
-                        && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
-                    dispatchTap(mAmbientIndicationContainer, viewX, viewY);
-                }
-            }
-        }
-
-        @Override
-        public void setDozeScreenBrightness(int value) {
-            mStatusBarWindowController.setDozeScreenBrightness(value);
-        }
-
-        @Override
-        public void setAodDimmingScrim(float scrimOpacity) {
-            mScrimController.setAodFrontScrimAlpha(scrimOpacity);
-        }
-
-        @Override
-        public void prepareForGentleSleep(Runnable onDisplayOffCallback) {
-            if (onDisplayOffCallback != null) {
-                Log.w(TAG, "Overlapping onDisplayOffCallback. Ignoring previous one.");
-            }
-            mPendingScreenOffCallback = onDisplayOffCallback;
-            updateScrimController();
-        }
-
-        /**
-         * When the dozing host is waiting for scrims to fade out to change the display state.
-         */
-        boolean hasPendingScreenOffCallback() {
-            return mPendingScreenOffCallback != null;
-        }
-
-        /**
-         * Executes an nullifies the pending display state callback.
-         *
-         * @see #hasPendingScreenOffCallback()
-         * @see #prepareForGentleSleep(Runnable)
-         */
-        void executePendingScreenOffCallback() {
-            if (mPendingScreenOffCallback == null) {
-                return;
-            }
-            mPendingScreenOffCallback.run();
-            mPendingScreenOffCallback = null;
-        }
-
-        private void dispatchTap(View view, float x, float y) {
-            long now = SystemClock.elapsedRealtime();
-            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN);
-            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP);
-        }
-
-        private void dispatchTouchEvent(View view, float x, float y, long now, int action) {
-            MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */);
-            view.dispatchTouchEvent(ev);
-            ev.recycle();
-        }
-
-        private boolean shouldAnimateWakeup() {
-            return mAnimateWakeup;
-        }
-
-        public boolean shouldAnimateScreenOff() {
-            return mAnimateScreenOff;
-        }
-    }
-
     public boolean shouldIgnoreTouch() {
-        return isDozing() && mDozeServiceHost.mIgnoreTouchWhilePulsing;
+        return isDozing() && mDozeServiceHost.getIgnoreTouchWhilePulsing();
     }
 
     // Begin Extra BaseStatusBar methods.
@@ -4352,7 +4109,7 @@
     private boolean mVisibleToUser;
 
     protected DevicePolicyManager mDevicePolicyManager;
-    protected PowerManager mPowerManager;
+    private final PowerManager mPowerManager;
     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     protected KeyguardManager mKeyguardManager;
@@ -4722,8 +4479,8 @@
         void createStatusBar(StatusBar statusbar);
     }
 
-    public @TransitionMode int getStatusBarMode() {
-        return mStatusBarMode;
+    boolean isTransientShown() {
+        return mTransientShown;
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index dfec195..64a45e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -245,7 +245,7 @@
         StatusBarNotification parentToCancel = null;
         if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
             StatusBarNotification summarySbn =
-                    mGroupManager.getLogicalGroupSummary(sbn).notification;
+                    mGroupManager.getLogicalGroupSummary(sbn).getSbn();
             if (shouldAutoCancel(summarySbn)) {
                 parentToCancel = summarySbn;
             }
@@ -310,7 +310,7 @@
         if (!TextUtils.isEmpty(entry.remoteInputText)) {
             remoteInputText = entry.remoteInputText;
         }
-        if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.key)) {
+        if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.getKey())) {
             fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
                     remoteInputText.toString());
         }
@@ -409,11 +409,11 @@
         if (mNotificationInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
             if (shouldSuppressFullScreenIntent(entry)) {
                 if (DEBUG) {
-                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.key);
+                    Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.getKey());
                 }
             } else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
                 if (DEBUG) {
-                    Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.key);
+                    Log.d(TAG, "No Fullscreen intent: not important enough: " + entry.getKey());
                 }
             } else {
                 // Stop screensaver if the notification has a fullscreen intent.
@@ -432,8 +432,8 @@
                 }
                 try {
                     EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
-                            entry.key);
-                    entry.notification.getNotification().fullScreenIntent.send();
+                            entry.getKey());
+                    entry.getSbn().getNotification().fullScreenIntent.send();
                     entry.notifyFullScreenIntentLaunched();
                     mMetricsLogger.count("note_fullscreen", 1);
                 } catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index f4a26ba..b01a8d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -201,7 +201,7 @@
                         NotificationVisibility visibility,
                         boolean removedByUser) {
                     StatusBarNotificationPresenter.this.onNotificationRemoved(
-                            entry.key, entry.notification);
+                            entry.getKey(), entry.getSbn());
                     if (removedByUser) {
                         maybeEndAmbientPulse();
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index d04c7bd..6b51391 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -23,6 +23,7 @@
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
+import android.graphics.Insets;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -42,6 +43,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
+import android.view.WindowInsets;
 import android.view.WindowInsetsController;
 import android.widget.FrameLayout;
 
@@ -74,7 +76,8 @@
     }
 
     @Override
-    protected boolean fitSystemWindows(Rect insets) {
+    public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
+        final Insets insets = windowInsets.getMaxInsets(WindowInsets.Type.systemBars());
         if (getFitsSystemWindows()) {
             boolean paddingChanged = insets.top != getPaddingTop()
                     || insets.bottom != getPaddingBottom();
@@ -100,9 +103,6 @@
             if (paddingChanged) {
                 setPadding(0, 0, 0, 0);
             }
-            insets.left = 0;
-            insets.top = 0;
-            insets.right = 0;
         } else {
             if (mRightInset != 0 || mLeftInset != 0) {
                 mRightInset = 0;
@@ -116,9 +116,8 @@
             if (changed) {
                 setPadding(0, 0, 0, 0);
             }
-            insets.top = 0;
         }
-        return false;
+        return windowInsets;
     }
 
     private void applyMargins() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 0a2fb2e..76683b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
-import static com.android.systemui.Dependency.MAIN_LOOPER_NAME;
-
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothAdapter;
@@ -36,6 +33,8 @@
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.MainLooper;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -46,7 +45,6 @@
 import java.util.WeakHashMap;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -74,9 +72,8 @@
     /**
      */
     @Inject
-    public BluetoothControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
-            @Named(MAIN_LOOPER_NAME) Looper mainLooper,
-            @Nullable LocalBluetoothManager localBluetoothManager) {
+    public BluetoothControllerImpl(Context context, @BgLooper Looper bgLooper,
+            @MainLooper Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) {
         mLocalBluetoothManager = localBluetoothManager;
         mBgHandler = new Handler(bgLooper);
         mHandler = new H(mainLooper);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index 089d5c9..0a40b3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -14,8 +14,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -26,12 +24,12 @@
 import android.provider.Settings.Secure;
 import android.util.Log;
 
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.settings.CurrentUserTracker;
 
 import java.util.ArrayList;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -51,8 +49,7 @@
     /**
      */
     @Inject
-    public DeviceProvisionedControllerImpl(Context context,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+    public DeviceProvisionedControllerImpl(Context context, @MainHandler Handler mainHandler) {
         super(context);
         mContext = context;
         mContentResolver = context.getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
index cade5dc..3ce6239 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java
@@ -57,7 +57,7 @@
         ExtensionBuilder<T> withCallback(Consumer<T> callback);
         ExtensionBuilder<T> withUiMode(int mode, Supplier<T> def);
         ExtensionBuilder<T> withFeature(String feature, Supplier<T> def);
-        Extension build();
+        Extension<T> build();
     }
 
     public interface PluginConverter<T, P> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
index fd030d1..eeef726 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -135,7 +135,7 @@
         }
 
         @Override
-        public ExtensionController.Extension build() {
+        public ExtensionController.Extension<T> build() {
             // Sort items in ascending order
             Collections.sort(mExtension.mProducers, Comparator.comparingInt(Item::sortOrder));
             mExtension.notifyChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index b84dc47..6828c32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -117,7 +117,7 @@
     }
 
     protected boolean hasFullScreenIntent(@NonNull NotificationEntry entry) {
-        return entry.notification.getNotification().fullScreenIntent != null;
+        return entry.getSbn().getNotification().fullScreenIntent != null;
     }
 
     protected void setEntryPinned(
@@ -206,7 +206,7 @@
     public void snooze() {
         for (String key : mAlertEntries.keySet()) {
             AlertEntry entry = getHeadsUpEntry(key);
-            String packageName = entry.mEntry.notification.getPackageName();
+            String packageName = entry.mEntry.getSbn().getPackageName();
             mSnoozedPackages.put(snoozeKey(packageName, mUser),
                     mClock.currentTimeMillis() + mSnoozeLengthMs);
         }
@@ -328,8 +328,8 @@
      * one should be ranked higher and 0 if they are equal.
      */
     public int compare(@NonNull NotificationEntry a, @NonNull NotificationEntry b) {
-        AlertEntry aEntry = getHeadsUpEntry(a.key);
-        AlertEntry bEntry = getHeadsUpEntry(b.key);
+        AlertEntry aEntry = getHeadsUpEntry(a.getKey());
+        AlertEntry bEntry = getHeadsUpEntry(b.getKey());
         if (aEntry == null || bEntry == null) {
             return aEntry == null ? 1 : -1;
         }
@@ -341,7 +341,7 @@
      * until it's collapsed again.
      */
     public void setExpanded(@NonNull NotificationEntry entry, boolean expanded) {
-        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.key);
+        HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
         if (headsUpEntry != null && entry.isRowPinned()) {
             headsUpEntry.setExpanded(expanded);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 1c6d12f..8f201c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.app.ActivityManager;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -26,12 +24,13 @@
 import android.os.UserManager;
 import android.util.Log;
 
+import com.android.systemui.dagger.qualifiers.MainHandler;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -56,7 +55,7 @@
     /**
      */
     @Inject
-    public HotspotControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+    public HotspotControllerImpl(Context context, @MainHandler Handler mainHandler) {
         mContext = context;
         mConnectivityManager =
                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
index be27741..c6ae669 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
@@ -144,13 +144,13 @@
             return false;
         }
         // If we are showing the spinner we don't want to add the buttons.
-        boolean showingSpinner = entry.notification.getNotification()
+        boolean showingSpinner = entry.getSbn().getNotification()
                 .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false);
         if (showingSpinner) {
             return false;
         }
         // If we are keeping the notification around while sending we don't want to add the buttons.
-        boolean hideSmartReplies = entry.notification.getNotification()
+        boolean hideSmartReplies = entry.getSbn().getNotification()
                 .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
         if (hideSmartReplies) {
             return false;
@@ -168,7 +168,7 @@
     public static SmartRepliesAndActions chooseSmartRepliesAndActions(
             SmartReplyConstants smartReplyConstants,
             final NotificationEntry entry) {
-        Notification notification = entry.notification.getNotification();
+        Notification notification = entry.getSbn().getNotification();
         Pair<RemoteInput, Notification.Action> remoteInputActionPair =
                 notification.findRemoteInputActionPair(false /* freeform */);
         Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
@@ -177,7 +177,7 @@
         if (!smartReplyConstants.isEnabled()) {
             if (DEBUG) {
                 Log.d(TAG, "Smart suggestions not enabled, not adding suggestions for "
-                        + entry.notification.getKey());
+                        + entry.getSbn().getKey());
             }
             return new SmartRepliesAndActions(null, null);
         }
@@ -271,7 +271,7 @@
      * through the remote input.
      */
     public static boolean hasFreeformRemoteInput(NotificationEntry entry) {
-        Notification notification = entry.notification.getNotification();
+        Notification notification = entry.getSbn().getNotification();
         return null != notification.findRemoteInputActionPair(true /* freeform */);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 683cdbb..5a97eed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.policy;
 
 import static com.android.settingslib.Utils.updateLocationEnabled;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
 
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
@@ -36,13 +35,13 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.android.systemui.dagger.qualifiers.BgLooper;
 import com.android.systemui.util.Utils;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -66,7 +65,7 @@
     private final H mHandler = new H();
 
     @Inject
-    public LocationControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
+    public LocationControllerImpl(Context context, @BgLooper Looper bgLooper) {
         mContext = context;
 
         // Register to listen for changes in location settings.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 7b5d489..60784c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -24,7 +24,6 @@
 import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 
 import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -65,6 +64,7 @@
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgLooper;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
@@ -81,7 +81,6 @@
 import java.util.Map;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /** Platform implementation of the network controller. **/
@@ -170,7 +169,7 @@
      * Construct this controller object and register for updates.
      */
     @Inject
-    public NetworkControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
+    public NetworkControllerImpl(Context context, @BgLooper Looper bgLooper,
             DeviceProvisionedController deviceProvisionedController) {
         this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index cca9479..502a9bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -175,7 +175,7 @@
         results.put(contentType, data);
         try {
             mStatusBarManagerService.grantInlineReplyUriPermission(
-                    mEntry.notification.getKey(), data);
+                    mEntry.getSbn().getKey(), data);
         } catch (Exception e) {
             Log.e(TAG, "Failed to grant URI permissions:" + e.getMessage(), e);
         }
@@ -191,7 +191,7 @@
         mProgressBar.setVisibility(VISIBLE);
         mEntry.remoteInputText = mEditText.getText();
         mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
-        mController.addSpinning(mEntry.key, mToken);
+        mController.addSpinning(mEntry.getKey(), mToken);
         mController.removeRemoteInput(mEntry, mToken);
         mEditText.mShowImeOnInputConnection = false;
         mController.remoteInputSent(mEntry);
@@ -203,17 +203,17 @@
         // but that's an edge case, and also because we can't always know which package will receive
         // an intent, so we just reset for the publisher.
         getContext().getSystemService(ShortcutManager.class).onApplicationActive(
-                mEntry.notification.getPackageName(),
-                mEntry.notification.getUser().getIdentifier());
+                mEntry.getSbn().getPackageName(),
+                mEntry.getSbn().getUser().getIdentifier());
 
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_SEND,
-                mEntry.notification.getPackageName());
+                mEntry.getSbn().getPackageName());
         try {
             mPendingIntent.send(mContext, 0, intent);
         } catch (PendingIntent.CanceledException e) {
             Log.i(TAG, "Unable to send remote input result", e);
             MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_FAIL,
-                    mEntry.notification.getPackageName());
+                    mEntry.getSbn().getPackageName());
         }
     }
 
@@ -228,7 +228,7 @@
                 LayoutInflater.from(context).inflate(R.layout.remote_input, root, false);
         v.mController = controller;
         v.mEntry = entry;
-        UserHandle user = computeTextOperationUser(entry.notification.getUser());
+        UserHandle user = computeTextOperationUser(entry.getSbn().getUser());
         v.mEditText.mUser = user;
         v.mEditText.setTextOperationUser(user);
         v.setTag(VIEW_TAG);
@@ -284,7 +284,7 @@
         mRemoteInputQuickSettingsDisabler.setRemoteInputActive(false);
 
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
-                mEntry.notification.getPackageName());
+                mEntry.getSbn().getPackageName());
     }
 
     @Override
@@ -304,7 +304,7 @@
             return;
         }
         mController.removeRemoteInput(mEntry, mToken);
-        mController.removeSpinning(mEntry.key, mToken);
+        mController.removeSpinning(mEntry.getKey(), mToken);
     }
 
     public void setPendingIntent(PendingIntent pendingIntent) {
@@ -349,7 +349,7 @@
 
     public void focus() {
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_OPEN,
-                mEntry.notification.getPackageName());
+                mEntry.getSbn().getPackageName());
 
         setVisibility(VISIBLE);
         if (mWrapper != null) {
@@ -388,7 +388,7 @@
         mEditText.setEnabled(true);
         mSendButton.setVisibility(VISIBLE);
         mProgressBar.setVisibility(INVISIBLE);
-        mController.removeSpinning(mEntry.key, mToken);
+        mController.removeSpinning(mEntry.getKey(), mToken);
         updateSendButton();
         onDefocus(false /* animate */);
 
@@ -540,7 +540,7 @@
     }
 
     public boolean isSending() {
-        return getVisibility() == VISIBLE && mController.isSpinning(mEntry.key, mToken);
+        return getVisibility() == VISIBLE && mController.isSpinning(mEntry.getKey(), mToken);
     }
 
     /**
@@ -679,8 +679,8 @@
                         }
                     };
 
-            InputConnection ic = InputConnectionCompat.createWrapper(
-                    inputConnection, outAttrs, callback);
+            InputConnection ic = inputConnection == null ? null :
+                    InputConnectionCompat.createWrapper(inputConnection, outAttrs, callback);
 
             Context userContext = null;
             try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index d88ae78..6edd75b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -15,8 +15,6 @@
  */
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.Dependency.BG_HANDLER_NAME;
-
 import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -50,6 +48,7 @@
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.BgHandler;
 import com.android.systemui.settings.CurrentUserTracker;
 
 import java.io.FileDescriptor;
@@ -57,7 +56,6 @@
 import java.util.ArrayList;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -102,7 +100,7 @@
     /**
      */
     @Inject
-    public SecurityControllerImpl(Context context, @Named(BG_HANDLER_NAME) Handler bgHandler) {
+    public SecurityControllerImpl(Context context, @BgHandler Handler bgHandler) {
         this(context, bgHandler, null);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 655c29c..347d300 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.app.RemoteInput;
 import android.content.Context;
 import android.content.res.Resources;
@@ -30,9 +28,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 @Singleton
@@ -67,7 +65,7 @@
     private final KeyValueListParser mParser = new KeyValueListParser(',');
 
     @Inject
-    public SmartReplyConstants(@Named(MAIN_HANDLER_NAME) Handler handler, Context context) {
+    public SmartReplyConstants(@MainHandler Handler handler, Context context) {
         mHandler = handler;
         mContext = context;
         final Resources resources = mContext.getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index b5f660a..65bb28f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -350,7 +350,7 @@
                         () -> {
                             smartReplyController.smartActionClicked(
                                     entry, actionIndex, action, smartActions.fromAssistant);
-                            headsUpManager.removeNotification(entry.key, true);
+                            headsUpManager.removeNotification(entry.getKey(), true);
                         }, entry.getRow());
         if (useDelayedOnClickListener) {
             onClickListener = new DelayedOnClickListener(onClickListener,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 95ae23c..f2d2fae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -18,7 +18,6 @@
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
 
 import android.app.ActivityManager;
 import android.app.Dialog;
@@ -58,6 +57,7 @@
 import com.android.systemui.Prefs.Key;
 import com.android.systemui.R;
 import com.android.systemui.SystemUISecondaryUserService;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.tiles.UserDetailView;
@@ -70,7 +70,6 @@
 import java.util.List;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -110,7 +109,7 @@
 
     @Inject
     public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
-            @Named(MAIN_HANDLER_NAME) Handler handler, ActivityStarter activityStarter) {
+            @MainHandler Handler handler, ActivityStarter activityStarter) {
         mContext = context;
         if (!UserManager.isGuestUserEphemeral()) {
             mGuestResumeSessionReceiver.register(context);
@@ -314,7 +313,6 @@
         // adb shell settings put system enable_fullscreen_user_switcher 1  # Turn it on.
         // Restart SystemUI or adb reboot.
         final int DEFAULT = -1;
-        // TODO(b/140061064)
         final int overrideUseFullscreenUserSwitcher =
                 whitelistIpcs(() -> Settings.System.getInt(mContext.getContentResolver(),
                         "enable_fullscreen_user_switcher", DEFAULT));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 29c42d2..1c7a195 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.NotificationManager;
@@ -41,6 +39,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.util.Utils;
@@ -51,7 +50,6 @@
 import java.util.Objects;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /** Platform implementation of the zen mode controller. **/
@@ -79,7 +77,7 @@
     private NotificationManager.Policy mConsolidatedNotificationPolicy;
 
     @Inject
-    public ZenModeControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
+    public ZenModeControllerImpl(Context context, @MainHandler Handler handler) {
         super(context);
         mContext = context;
         mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
index d6d0a36..9b685f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
@@ -30,6 +30,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.widget.ImageView;
@@ -45,7 +46,10 @@
     private static final String TAG = "AudioRecordingDisclosureBar";
     private static final boolean DEBUG = false;
 
-    private static final String LAYOUT_PARAMS_TITLE = "AudioRecordingDisclosureBar";
+    // This title is used to test the microphone disclosure indicator in
+    // CtsSystemUiHostTestCases:TvMicrophoneCaptureIndicatorTest
+    private static final String LAYOUT_PARAMS_TITLE = "MicrophoneCaptureIndicator";
+
     private static final int ANIM_DURATION_MS = 150;
 
     private final Context mContext;
@@ -70,6 +74,7 @@
     }
 
     private void createView() {
+        //TODO(b/142228704): this is to be re-implemented once proper design is completed
         mView = View.inflate(mContext,
                 R.layout.tv_status_bar_audio_recording, null);
         mAppsInfoContainer = mView.findViewById(R.id.container);
@@ -88,7 +93,7 @@
                 Context.WINDOW_SERVICE);
         windowManager.addView(mView, layoutParams);
 
-        // Set invisible first util it gains its actual size and we are able to hide it by moving
+        // Set invisible first until it gains its actual size and we are able to hide it by moving
         // off the screen
         mView.setVisibility(View.INVISIBLE);
         mView.getViewTreeObserver().addOnGlobalLayoutListener(
@@ -98,16 +103,18 @@
                         // Now that we get the height, we can move the bar off ("below") the screen
                         final int height = mView.getHeight();
                         mView.setTranslationY(height);
-                        // ... and make it visible
-                        mView.setVisibility(View.VISIBLE);
                         // Remove the observer
                         mView.getViewTreeObserver()
                                 .removeOnGlobalLayoutListener(this);
+                        // Now, that the view has been measured, and the translation was set to
+                        // move it off the screen, we change the visibility to GONE
+                        mView.setVisibility(View.GONE);
                     }
                 });
     }
 
     private void showAudioRecordingDisclosureBar() {
+        mView.setVisibility(View.VISIBLE);
         mView.animate()
                 .translationY(0f)
                 .setDuration(ANIM_DURATION_MS)
@@ -138,9 +145,10 @@
     }
 
     private void hideAudioRecordingDisclosureBar() {
-        mView.animate()
-                .translationY(mView.getHeight())
+        final ViewPropertyAnimator animator = mView.animate();
+        animator.translationY(mView.getHeight())
                 .setDuration(ANIM_DURATION_MS)
+                .withEndAction(() -> mView.setVisibility(View.GONE))
                 .start();
     }
 
@@ -156,7 +164,7 @@
         public void onOpActiveChanged(String op, int uid, String packageName, boolean active) {
             if (DEBUG) {
                 Log.d(TAG,
-                        "OP_RECORD_AUDIO active change, active" + active + ", app=" + packageName);
+                        "OP_RECORD_AUDIO active change, active=" + active + ", app=" + packageName);
             }
 
             if (mExemptApps.contains(packageName)) {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index a55e2cf..2d6027c 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -15,8 +15,6 @@
  */
 package com.android.systemui.tuner;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
 import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -36,6 +34,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.DemoMode;
+import com.android.systemui.dagger.qualifiers.MainHandler;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -46,7 +45,6 @@
 import java.util.Set;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 
@@ -83,7 +81,7 @@
     /**
      */
     @Inject
-    public TunerServiceImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler,
+    public TunerServiceImpl(Context context, @MainHandler Handler mainHandler,
             LeakDetector leakDetector) {
         mContext = context;
         mContentResolver = mContext.getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 7e801da..5ed027d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -26,7 +26,7 @@
 import com.android.keyguard.KeyguardClockSwitch;
 import com.android.keyguard.KeyguardMessageArea;
 import com.android.keyguard.KeyguardSliceView;
-import com.android.systemui.SystemUIRootComponent;
+import com.android.systemui.dagger.SystemUIRootComponent;
 import com.android.systemui.qs.QSCarrierGroup;
 import com.android.systemui.qs.QSFooterImpl;
 import com.android.systemui.qs.QSPanel;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 63db755..bff405c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -20,7 +20,6 @@
 import static android.telephony.ims.feature.ImsFeature.STATE_UNAVAILABLE;
 
 import static com.android.internal.logging.MetricsLogger.VIEW_UNKNOWN;
-import static com.android.systemui.Dependency.BG_LOOPER_NAME;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -48,6 +47,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
+import com.android.systemui.dagger.qualifiers.BgLooper;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSHost;
@@ -59,7 +59,6 @@
 import java.util.List;
 
 import javax.inject.Inject;
-import javax.inject.Named;
 import javax.inject.Singleton;
 
 /**
@@ -110,7 +109,7 @@
     @Inject
     public GarbageMonitor(
             Context context,
-            @Named(BG_LOOPER_NAME) Looper bgLooper,
+            @BgLooper Looper bgLooper,
             LeakDetector leakDetector,
             LeakReporter leakReporter) {
         mContext = context.getApplicationContext();
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index cce5bca..a96977a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.util.sensors;
 
-import android.content.Context;
+import android.content.res.Resources;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
@@ -26,6 +26,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.MainResources;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -64,9 +65,10 @@
     };
 
     @Inject
-    public ProximitySensor(Context context, AsyncSensorManager sensorManager) {
+    public ProximitySensor(@MainResources Resources resources,
+            AsyncSensorManager sensorManager) {
         mSensorManager = sensorManager;
-        Sensor sensor = findBrightnessSensor(context);
+        Sensor sensor = findBrightnessSensor(resources);
 
         if (sensor == null) {
             mUsingBrightnessSensor = false;
@@ -106,8 +108,8 @@
         registerInternal();
     }
 
-    private Sensor findBrightnessSensor(Context context) {
-        String sensorType = context.getString(R.string.doze_brightness_sensor_type);
+    private Sensor findBrightnessSensor(Resources resources) {
+        String sensorType = resources.getString(R.string.doze_brightness_sensor_type);
         List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
         Sensor sensor = null;
         for (Sensor s : sensorList) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index 7991e38..e4ebea9 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -16,8 +16,11 @@
 
 package com.android.systemui.util.wakelock;
 
+import android.content.Context;
 import android.os.Handler;
 
+import javax.inject.Inject;
+
 /**
  * A wake lock that has a built in delay when releasing to give the framebuffer time to update.
  */
@@ -53,4 +56,46 @@
     public String toString() {
         return TO_STRING_PREFIX + mInner;
     }
+
+    /**
+     * An injectable builder for {@see DelayedWakeLock} that has the context already filled in.
+     */
+    public static class Builder {
+        private final Context mContext;
+        private String mTag;
+        private Handler mHandler;
+
+        /**
+         * Constructor for DelayedWakeLock.Builder
+         */
+        @Inject
+        public Builder(Context context) {
+            mContext = context;
+        }
+
+        /**
+         * Set the tag for the WakeLock.
+         */
+        public Builder setTag(String tag) {
+            mTag = tag;
+
+            return this;
+        }
+
+        /**
+         * Set the handler for the DelayedWakeLock.
+         */
+        public Builder setHandler(Handler handler) {
+            mHandler = handler;
+
+            return this;
+        }
+
+        /**
+         * Build the DelayedWakeLock.
+         */
+        public DelayedWakeLock build() {
+            return new DelayedWakeLock(mHandler, WakeLock.createPartial(mContext, mTag));
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 5c4ef18..768bd13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -21,11 +21,15 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.annotation.UserIdInt;
+import android.app.AppOpsManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.os.Bundle;
@@ -42,6 +46,8 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
+import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -50,27 +56,104 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class ForegroundServiceControllerTest extends SysuiTestCase {
-    @UserIdInt private static final int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
-    @UserIdInt private static final int USERID_TWO = USERID_ONE + 1;
-
     private ForegroundServiceController mFsc;
     private ForegroundServiceNotificationListener mListener;
     private NotificationEntryListener mEntryListener;
+    private NotificationEntryManager mEntryManager;
 
     @Before
     public void setUp() throws Exception {
-        mFsc = new ForegroundServiceController();
-        NotificationEntryManager notificationEntryManager = mock(NotificationEntryManager.class);
+        mEntryManager = mock(NotificationEntryManager.class);
+        mFsc = new ForegroundServiceController(mEntryManager);
         mListener = new ForegroundServiceNotificationListener(
-                mContext, mFsc, notificationEntryManager);
+                mContext, mFsc, mEntryManager);
         ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
                 ArgumentCaptor.forClass(NotificationEntryListener.class);
-        verify(notificationEntryManager).addNotificationEntryListener(
+        verify(mEntryManager).addNotificationEntryListener(
                 entryListenerCaptor.capture());
         mEntryListener = entryListenerCaptor.getValue();
     }
 
     @Test
+    public void testAppOps_appOpChangedBeforeNotificationExists() {
+        // GIVEN app op exists, but notification doesn't exist in NEM yet
+        NotificationEntry entry = createFgEntry();
+        mFsc.onAppOpChanged(
+                AppOpsManager.OP_CAMERA,
+                entry.getSbn().getUid(),
+                entry.getSbn().getPackageName(),
+                true);
+        assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+        // WHEN the notification is added
+        mEntryListener.onPendingEntryAdded(entry);
+
+        // THEN the app op is added to the entry
+        Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+    }
+
+    @Test
+    public void testAppOps_appOpAddedToForegroundNotif() {
+        // GIVEN a notification associated with a foreground service
+        NotificationEntry entry = addFgEntry();
+        when(mEntryManager.getPendingOrCurrentNotif(entry.getKey())).thenReturn(entry);
+
+        // WHEN we are notified of a new app op for this notification
+        mFsc.onAppOpChanged(
+                AppOpsManager.OP_CAMERA,
+                entry.getSbn().getUid(),
+                entry.getSbn().getPackageName(),
+                true);
+
+        // THEN the app op is added to the entry
+        Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+        // THEN notification views are updated since the notification is visible
+        verify(mEntryManager, times(1)).updateNotifications(anyString());
+    }
+
+    @Test
+    public void testAppOpsAlreadyAdded() {
+        // GIVEN a foreground service associated notification that already has the correct app op
+        NotificationEntry entry = addFgEntry();
+        entry.mActiveAppOps.add(AppOpsManager.OP_CAMERA);
+        when(mEntryManager.getPendingOrCurrentNotif(entry.getKey())).thenReturn(entry);
+
+        // WHEN we are notified of the same app op for this notification
+        mFsc.onAppOpChanged(
+                AppOpsManager.OP_CAMERA,
+                entry.getSbn().getUid(),
+                entry.getSbn().getPackageName(),
+                true);
+
+        // THEN the app op still exists in the notification entry
+        Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+        // THEN notification views aren't updated since nothing changed
+        verify(mEntryManager, never()).updateNotifications(anyString());
+    }
+
+    @Test
+    public void testAppOps_appOpNotAddedToUnrelatedNotif() {
+        // GIVEN no notification entries correspond to the newly updated appOp
+        NotificationEntry entry = addFgEntry();
+        when(mEntryManager.getPendingOrCurrentNotif(entry.getKey())).thenReturn(null);
+
+        // WHEN a new app op is detected
+        mFsc.onAppOpChanged(
+                AppOpsManager.OP_CAMERA,
+                entry.getSbn().getUid(),
+                entry.getSbn().getPackageName(),
+                true);
+
+        // THEN we won't see appOps on the entry
+        Assert.assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+        // THEN notification views aren't updated since nothing changed
+        verify(mEntryManager, never()).updateNotifications(anyString());
+    }
+
+    @Test
     public void testAppOpsCRUD() {
         // no crash on remove that doesn't exist
         mFsc.onAppOpChanged(9, 1000, "pkg1", false);
@@ -339,12 +422,12 @@
         assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1));
     }
 
-    private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
+    private StatusBarNotification makeMockSBN(int userId, String pkg, int id, String tag,
             int flags) {
         final Notification n = mock(Notification.class);
         n.extras = new Bundle();
         n.flags = flags;
-        return makeMockSBN(userid, pkg, id, tag, n);
+        return makeMockSBN(userId, pkg, id, tag, n);
     }
 
     private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
@@ -360,10 +443,10 @@
         return sbn;
     }
 
-    private StatusBarNotification makeMockFgSBN(int userid, String pkg, int id,
+    private StatusBarNotification makeMockFgSBN(int uid, String pkg, int id,
             boolean usesStdLayout) {
         StatusBarNotification sbn =
-                makeMockSBN(userid, pkg, id, "foo", Notification.FLAG_FOREGROUND_SERVICE);
+                makeMockSBN(uid, pkg, id, "foo", Notification.FLAG_FOREGROUND_SERVICE);
         if (usesStdLayout) {
             sbn.getNotification().contentView = null;
             sbn.getNotification().headsUpContentView = null;
@@ -374,8 +457,8 @@
         return sbn;
     }
 
-    private StatusBarNotification makeMockFgSBN(int userid, String pkg) {
-        return makeMockSBN(userid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
+    private StatusBarNotification makeMockFgSBN(int uid, String pkg) {
+        return makeMockSBN(uid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
     }
 
     private StatusBarNotification makeMockDisclosure(int userid, String[] pkgs) {
@@ -392,6 +475,19 @@
         return sbn;
     }
 
+    private NotificationEntry addFgEntry() {
+        NotificationEntry entry = createFgEntry();
+        mEntryListener.onPendingEntryAdded(entry);
+        return entry;
+    }
+
+    private NotificationEntry createFgEntry() {
+        return new NotificationEntryBuilder()
+                .setSbn(makeMockFgSBN(0, TEST_PACKAGE_NAME, 1000, true))
+                .setImportance(NotificationManager.IMPORTANCE_DEFAULT)
+                .build();
+    }
+
     private void entryRemoved(StatusBarNotification notification) {
         mEntryListener.onEntryRemoved(
                 new NotificationEntryBuilder()
@@ -414,6 +510,10 @@
                 .setSbn(notification)
                 .setImportance(importance)
                 .build();
-        mEntryListener.onPostEntryUpdated(entry);
+        mEntryListener.onPreEntryUpdated(entry);
     }
+
+    @UserIdInt private static final int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
+    @UserIdInt private static final int USERID_TWO = USERID_ONE + 1;
+    private static final String TEST_PACKAGE_NAME = "test";
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index c338d70..7359fdce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -61,9 +61,13 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.util.Collections;
 
+import dagger.Lazy;
+
 @RunWithLooper
 @RunWith(AndroidTestingRunner.class)
 @SmallTest
@@ -71,16 +75,19 @@
 
     private TestableLooper mTestableLooper;
     private ScreenDecorations mScreenDecorations;
-    private StatusBar mStatusBar;
+    @Mock private StatusBar mStatusBar;
     private WindowManager mWindowManager;
     private FragmentService mFragmentService;
     private FragmentHostManager mFragmentHostManager;
     private TunerService mTunerService;
     private StatusBarWindowView mView;
     private TunablePaddingService mTunablePaddingService;
+    @Mock private Lazy<StatusBar> mStatusBarLazy;
 
     @Before
     public void setup() {
+        MockitoAnnotations.initMocks(this);
+
         mTestableLooper = TestableLooper.get(this);
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 new Handler(mTestableLooper.getLooper()));
@@ -88,11 +95,10 @@
         mTunerService = mDependency.injectMockDependency(TunerService.class);
         mFragmentService = mDependency.injectMockDependency(FragmentService.class);
 
-        mStatusBar = mock(StatusBar.class);
         mWindowManager = mock(WindowManager.class);
         mView = spy(new StatusBarWindowView(mContext, null));
+        when(mStatusBarLazy.get()).thenReturn(mStatusBar);
         when(mStatusBar.getStatusBarWindow()).thenReturn(mView);
-        mContext.putComponent(StatusBar.class, mStatusBar);
 
         Display display = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
         when(mWindowManager.getDefaultDisplay()).thenReturn(display);
@@ -102,7 +108,7 @@
         when(mFragmentService.getFragmentHostManager(any())).thenReturn(mFragmentHostManager);
 
 
-        mScreenDecorations = new ScreenDecorations(mContext) {
+        mScreenDecorations = new ScreenDecorations(mContext, mStatusBarLazy) {
             @Override
             public void start() {
                 super.start();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index e1eb3b0..85d818a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -38,15 +38,18 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.hardware.biometrics.Authenticator;
+import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
+import android.hardware.face.FaceManager;
 import android.os.Bundle;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableContext;
 import android.testing.TestableLooper.RunWithLooper;
 
+import com.android.internal.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -89,9 +92,9 @@
 
         when(context.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE))
-            .thenReturn(true);
+                .thenReturn(true);
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
-            .thenReturn(true);
+                .thenReturn(true);
 
         when(mDialog1.getOpPackageName()).thenReturn("Dialog1");
         when(mDialog2.getOpPackageName()).thenReturn("Dialog2");
@@ -170,20 +173,34 @@
     @Test
     public void testOnAuthenticationSucceededInvoked_whenSystemRequested() {
         showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
-        mAuthController.onBiometricAuthenticated(true, null /* failureReason */);
+        mAuthController.onBiometricAuthenticated();
         verify(mDialog1).onAuthenticationSucceeded();
     }
 
     @Test
-    public void testOnAuthenticationFailedInvoked_whenSystemRequested() {
+    public void testOnAuthenticationFailedInvoked_whenBiometricRejected() {
         showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
-        final String failureReason = "failure reason";
-        mAuthController.onBiometricAuthenticated(false, failureReason);
+        mAuthController.onBiometricError(BiometricAuthenticator.TYPE_NONE,
+                BiometricConstants.BIOMETRIC_PAUSED_REJECTED,
+                0 /* vendorCode */);
 
         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
         verify(mDialog1).onAuthenticationFailed(captor.capture());
 
-        assertEquals(captor.getValue(), failureReason);
+        assertEquals(captor.getValue(), mContext.getString(R.string.biometric_not_recognized));
+    }
+
+    @Test
+    public void testOnAuthenticationFailedInvoked_whenBiometricTimedOut() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        final int error = BiometricConstants.BIOMETRIC_ERROR_TIMEOUT;
+        final int vendorCode = 0;
+        mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode);
+
+        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+        verify(mDialog1).onAuthenticationFailed(captor.capture());
+
+        assertEquals(captor.getValue(), FaceManager.getErrorString(mContext, error, vendorCode));
     }
 
     @Test
@@ -199,27 +216,27 @@
     }
 
     @Test
-    public void testOnErrorInvoked_whenSystemRequested() {
+    public void testOnErrorInvoked_whenSystemRequested() throws Exception {
         showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         final int error = 1;
-        final String errMessage = "error message";
-        mAuthController.onBiometricError(error, errMessage);
+        final int vendorCode = 0;
+        mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode);
 
         ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
         verify(mDialog1).onError(captor.capture());
 
-        assertEquals(captor.getValue(), errMessage);
+        assertEquals(captor.getValue(), FaceManager.getErrorString(mContext, error, vendorCode));
     }
 
     @Test
     public void testErrorLockout_whenCredentialAllowed_AnimatesToCredentialUI() {
         showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT;
-        final String errorString = "lockout";
+        final int vendorCode = 0;
 
         when(mDialog1.isAllowDeviceCredentials()).thenReturn(true);
 
-        mAuthController.onBiometricError(error, errorString);
+        mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode);
         verify(mDialog1, never()).onError(anyString());
         verify(mDialog1).animateToCredentialUI();
     }
@@ -228,11 +245,11 @@
     public void testErrorLockoutPermanent_whenCredentialAllowed_AnimatesToCredentialUI() {
         showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
-        final String errorString = "lockout_permanent";
+        final int vendorCode = 0;
 
         when(mDialog1.isAllowDeviceCredentials()).thenReturn(true);
 
-        mAuthController.onBiometricError(error, errorString);
+        mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode);
         verify(mDialog1, never()).onError(anyString());
         verify(mDialog1).animateToCredentialUI();
     }
@@ -241,12 +258,12 @@
     public void testErrorLockout_whenCredentialNotAllowed_sendsOnError() {
         showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT;
-        final String errorString = "lockout";
+        final int vendorCode = 0;
 
         when(mDialog1.isAllowDeviceCredentials()).thenReturn(false);
 
-        mAuthController.onBiometricError(error, errorString);
-        verify(mDialog1).onError(eq(errorString));
+        mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode);
+        verify(mDialog1).onError(eq(FaceManager.getErrorString(mContext, error, vendorCode)));
         verify(mDialog1, never()).animateToCredentialUI();
     }
 
@@ -254,12 +271,12 @@
     public void testErrorLockoutPermanent_whenCredentialNotAllowed_sendsOnError() {
         showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
         final int error = BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
-        final String errorString = "lockout_permanent";
+        final int vendorCode = 0;
 
         when(mDialog1.isAllowDeviceCredentials()).thenReturn(false);
 
-        mAuthController.onBiometricError(error, errorString);
-        verify(mDialog1).onError(eq(errorString));
+        mAuthController.onBiometricError(BiometricAuthenticator.TYPE_FACE, error, vendorCode);
+        verify(mDialog1).onError(eq(FaceManager.getErrorString(mContext, error, vendorCode)));
         verify(mDialog1, never()).animateToCredentialUI();
     }
 
@@ -372,6 +389,20 @@
         verify(mReceiver).onDialogDismissed(eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL));
     }
 
+    @Test
+    public void testDoesNotCrash_whenTryAgainPressedAfterDismissal() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED);
+        mAuthController.onTryAgainPressed();
+    }
+
+    @Test
+    public void testDoesNotCrash_whenDeviceCredentialPressedAfterDismissal() {
+        showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+        mAuthController.onDismissed(AuthDialogCallback.DISMISSED_USER_CANCELED);
+        mAuthController.onDeviceCredentialPressed();
+    }
+
     // Helpers
 
     private void showDialog(int authenticators, int biometricModality) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 3472573..0068113 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -172,8 +172,8 @@
 
         // Return non-null notification data from the NEM
         when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
-        when(mNotificationData.get(mRow.getEntry().key)).thenReturn(mRow.getEntry());
-        when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(
+        when(mNotificationData.get(mRow.getEntry().getKey())).thenReturn(mRow.getEntry());
+        when(mNotificationData.getChannel(mRow.getEntry().getKey())).thenReturn(
                 mRow.getEntry().getChannel());
 
         mZenModeConfig.suppressedVisualEffects = 0;
@@ -228,14 +228,15 @@
     @Test
     public void testRemoveBubble() {
         mBubbleController.updateBubble(mRow.getEntry());
-        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
+        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
         assertTrue(mBubbleController.hasBubbles());
         verify(mNotificationEntryManager).updateNotifications(any());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
 
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
-        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
+        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
         verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
     }
@@ -246,18 +247,20 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // Make it look like dismissed notif
-        mBubbleData.getBubbleWithKey(mRow.getEntry().key).setShowInShadeWhenBubble(false);
+        mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).setShowInShadeWhenBubble(false);
 
         // Now remove the bubble
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
 
         // Since the notif is dismissed, once the bubble is removed, performRemoveNotification gets
         // called to really remove the notif
         verify(mNotificationEntryManager, times(1)).performRemoveNotification(
-                mRow.getEntry().notification, UNDEFINED_DISMISS_REASON);
+                mRow.getEntry().getSbn(), UNDEFINED_DISMISS_REASON);
         assertFalse(mBubbleController.hasBubbles());
     }
 
@@ -265,17 +268,17 @@
     public void testDismissStack() {
         mBubbleController.updateBubble(mRow.getEntry());
         verify(mNotificationEntryManager, times(1)).updateNotifications(any());
-        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
+        assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
         mBubbleController.updateBubble(mRow2.getEntry());
         verify(mNotificationEntryManager, times(2)).updateNotifications(any());
-        assertNotNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
+        assertNotNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().getKey()));
         assertTrue(mBubbleController.hasBubbles());
 
         mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         verify(mNotificationEntryManager, times(3)).updateNotifications(any());
-        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
-        assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
+        assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
+        assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().getKey()));
     }
 
     @Test
@@ -288,22 +291,24 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         assertFalse(mStatusBarWindowController.getBubbleExpanded());
 
         // Expand the stack
         BubbleStackView stackView = mBubbleController.getStackView();
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
         assertTrue(mStatusBarWindowController.getBubbleExpanded());
 
         // Make sure the notif is suppressed
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // Collapse
         mBubbleController.collapseStack();
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
         assertFalse(mBubbleController.isStackExpanded());
         assertFalse(mStatusBarWindowController.getBubbleExpanded());
     }
@@ -318,30 +323,33 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
         assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
-                mRow2.getEntry().key));
+                mRow.getEntry().getKey()));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow2.getEntry().getKey()));
 
         // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
 
         // Last added is the one that is expanded
         assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow2.getEntry().getKey()));
 
         // Switch which bubble is expanded
-        mBubbleController.selectBubble(mRow.getEntry().key);
-        stackView.setExpandedBubble(mRow.getEntry().key);
+        mBubbleController.selectBubble(mRow.getEntry().getKey());
+        stackView.setExpandedBubble(mRow.getEntry().getKey());
         assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // collapse for previous bubble
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
         // expand for selected bubble
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Collapse
         mBubbleController.collapseStack();
@@ -356,18 +364,20 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
-        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
 
         // Expand
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Notif is suppressed after expansion
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // Notif shouldn't show dot after expansion
-        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
     }
 
     @Test
@@ -378,28 +388,31 @@
 
         // We should have bubbles & their notifs should not be suppressed
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
-        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
 
         // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
         mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Notif is suppressed after expansion
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // Notif shouldn't show dot after expansion
-        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
 
         // Send update
         mEntryListener.onPreEntryUpdated(mRow.getEntry());
 
         // Nothing should have changed
         // Notif is suppressed after expansion
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // Notif shouldn't show dot after expansion
-        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
     }
 
     @Test
@@ -416,27 +429,28 @@
         mBubbleController.expandStack();
 
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
 
         // Last added is the one that is expanded
         assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow2.getEntry().getKey()));
 
         // Dismiss currently expanded
         mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
 
         // Make sure first bubble is selected
         assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
 
         // Dismiss that one
         mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
 
         // Make sure state changes and collapse happens
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().getKey());
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
         assertFalse(mBubbleController.hasBubbles());
     }
@@ -453,7 +467,7 @@
 
         // Expansion shouldn't change
         verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
-                mRow.getEntry().key);
+                mRow.getEntry().getKey());
         assertFalse(mBubbleController.isStackExpanded());
 
         // # of bubbles should change
@@ -471,7 +485,7 @@
 
         // Expansion should change
         verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
-                mRow.getEntry().key);
+                mRow.getEntry().getKey());
         assertTrue(mBubbleController.isStackExpanded());
 
         // # of bubbles should change
@@ -488,7 +502,8 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         // Should not be suppressed because we weren't forground
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
     }
@@ -503,7 +518,8 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         // Notif should be suppressed because we were foreground
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // # of bubbles should change
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
@@ -511,13 +527,14 @@
 
     @Test
     public void testExpandStackAndSelectBubble_removedFirst() {
-        final String key = mRow.getEntry().key;
+        final String key = mRow.getEntry().getKey();
 
         mEntryListener.onPendingEntryAdded(mRow.getEntry());
         mBubbleController.updateBubble(mRow.getEntry());
 
         // Simulate notification cancellation.
-        mRemoveInterceptor.onNotificationRemoveRequested(mRow.getEntry().key, REASON_APP_CANCEL);
+        mRemoveInterceptor.onNotificationRemoveRequested(
+                mRow.getEntry().getKey(), REASON_APP_CANCEL);
 
         mBubbleController.expandStackAndSelectBubble(key);
     }
@@ -525,8 +542,9 @@
     @Test
     public void testMarkNewNotificationAsShowInShade() {
         mEntryListener.onPendingEntryAdded(mRow.getEntry());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
-        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().key).showBubbleDot());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+        assertTrue(mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).showBubbleDot());
     }
 
     @Test
@@ -541,14 +559,15 @@
     @Test
     public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_AGED);
+        mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED);
         verify(mDeleteIntent, never()).send();
     }
 
     @Test
     public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
         mBubbleController.updateBubble(mRow.getEntry());
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         verify(mDeleteIntent, times(1)).send();
     }
 
@@ -566,7 +585,7 @@
         mBubbleController.updateBubble(mRow.getEntry());
         assertTrue(mBubbleController.hasBubbles());
 
-        mRow.getEntry().notification.getNotification().flags &= ~FLAG_BUBBLE;
+        mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
         mEntryListener.onPreEntryUpdated(mRow.getEntry());
 
         assertFalse(mBubbleController.hasBubbles());
@@ -581,7 +600,7 @@
         assertTrue(mBubbleController.hasBubbles());
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_APP_CANCEL);
+                mRow.getEntry().getKey(), REASON_APP_CANCEL);
 
         // Cancels always remove so no need to intercept
         assertFalse(intercepted);
@@ -594,15 +613,17 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_CANCEL_ALL);
+                mRow.getEntry().getKey(), REASON_CANCEL_ALL);
 
         // Intercept!
         assertTrue(intercepted);
         // Should update show in shade state
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         verify(mNotificationEntryManager, never()).performRemoveNotification(
                 any(), anyInt());
@@ -615,15 +636,17 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_CANCEL);
+                mRow.getEntry().getKey(), REASON_CANCEL);
 
         // Intercept!
         assertTrue(intercepted);
         // Should update show in shade state
-        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         verify(mNotificationEntryManager, never()).performRemoveNotification(
                 any(), anyInt());
@@ -636,15 +659,17 @@
         mBubbleController.updateBubble(mRow.getEntry());
 
         assertTrue(mBubbleController.hasBubbles());
-        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry().key));
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
 
         // Dismiss the bubble
-        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        mBubbleController.removeBubble(
+                mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mBubbleController.hasBubbles());
 
         // Dismiss the notification
         boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested(
-                mRow.getEntry().key, REASON_CANCEL);
+                mRow.getEntry().getKey(), REASON_CANCEL);
 
         // It's no longer a bubble so we shouldn't intercept
         assertFalse(intercepted);
@@ -694,7 +719,7 @@
      */
     private void setMetadataFlags(NotificationEntry entry, int flag, boolean enableFlag) {
         Notification.BubbleMetadata bubbleMetadata =
-                entry.notification.getNotification().getBubbleMetadata();
+                entry.getSbn().getNotification().getBubbleMetadata();
         int flags = bubbleMetadata.getFlags();
         if (enableFlag) {
             flags |= flag;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 96ee079..67f65e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -842,14 +842,14 @@
     }
 
     private void setPostTime(NotificationEntry entry, long postTime) {
-        when(entry.notification.getPostTime()).thenReturn(postTime);
+        when(entry.getSbn().getPostTime()).thenReturn(postTime);
     }
 
     private void setOngoing(NotificationEntry entry, boolean ongoing) {
         if (ongoing) {
-            entry.notification.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
+            entry.getSbn().getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
         } else {
-            entry.notification.getNotification().flags &= ~Notification.FLAG_FOREGROUND_SERVICE;
+            entry.getSbn().getNotification().flags &= ~Notification.FLAG_FOREGROUND_SERVICE;
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 777fec7..756227e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -83,7 +83,7 @@
         mDockManagerFake = mock(DockManager.class);
         AsyncSensorManager asyncSensorManager =
                 new AsyncSensorManager(mSensors, null, new Handler());
-        mProximitySensor = new FakeProximitySensor(getContext(), asyncSensorManager);
+        mProximitySensor = new FakeProximitySensor(getContext().getResources(), asyncSensorManager);
 
         mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, config, parameters,
                 asyncSensorManager, Handler.createAsync(Looper.myLooper()), wakeLock, true,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
new file mode 100644
index 0000000..9312ed2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.systemui.keyguard;
+
+import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class KeyguardViewMediatorTest extends SysuiTestCase {
+    private KeyguardViewMediator mViewMediator;
+
+    private @Mock DevicePolicyManager mDevicePolicyManager;
+    private @Mock LockPatternUtils mLockPatternUtils;
+    private @Mock KeyguardUpdateMonitor mUpdateMonitor;
+    private @Mock StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private @Mock StatusBarWindowController mStatusBarWindowController;
+    private @Mock SystemUIFactory mSystemUIFactory;
+
+    private FalsingManagerFake mFalsingManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mFalsingManager = new FalsingManagerFake();
+
+        mDependency.injectTestDependency(FalsingManager.class, mFalsingManager);
+        mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mUpdateMonitor);
+        mDependency.injectTestDependency(StatusBarWindowController.class,
+                mStatusBarWindowController);
+
+        when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
+        when(mSystemUIFactory.createStatusBarKeyguardViewManager(
+                any(Context.class),
+                any(ViewMediatorCallback.class),
+                any(LockPatternUtils.class))).thenReturn(mStatusBarKeyguardViewManager);
+
+        TestableLooper.get(this).runWithLooper(() -> {
+            mViewMediator = new KeyguardViewMediator(
+                    mContext, mFalsingManager, mLockPatternUtils, mSystemUIFactory);
+        });
+    }
+
+    @Test
+    public void testOnGoingToSleep_UpdatesKeyguardGoingAway() {
+        mViewMediator.start();
+        mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
+        verify(mUpdateMonitor).setKeyguardGoingAway(false);
+        verify(mStatusBarWindowController, never()).setKeyguardGoingAway(anyBoolean());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 8f4de3f..47b35fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -22,7 +22,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.anyObject;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -60,6 +59,8 @@
 import java.time.Duration;
 import java.util.concurrent.TimeUnit;
 
+import dagger.Lazy;
+
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
@@ -86,6 +87,8 @@
     private IThermalEventListener mUsbThermalEventListener;
     private IThermalEventListener mSkinThermalEventListener;
     @Mock private BroadcastDispatcher mBroadcastDispatcher;
+    @Mock private Lazy<StatusBar> mStatusBarLazy;
+    @Mock private StatusBar mStatusBar;
 
     @Before
     public void setup() {
@@ -93,7 +96,8 @@
         mMockWarnings = mDependency.injectMockDependency(WarningsUI.class);
         mEnhancedEstimates = mDependency.injectMockDependency(EnhancedEstimates.class);
 
-        mContext.putComponent(StatusBar.class, mock(StatusBar.class));
+        when(mStatusBarLazy.get()).thenReturn(mStatusBar);
+
         mContext.addMockSystemService(Context.POWER_SERVICE, mPowerManager);
 
         createPowerUi();
@@ -682,7 +686,7 @@
     }
 
     private void createPowerUi() {
-        mPowerUI = new PowerUI(mContext, mBroadcastDispatcher);
+        mPowerUI = new PowerUI(mContext, mBroadcastDispatcher, mStatusBarLazy);
         mPowerUI.mComponents = mContext.getComponents();
         mPowerUI.mThermalService = mThermalServiceMock;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index cf5a12f..c6dd232 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -141,9 +141,9 @@
     public void testShowNotification_addsEntry() {
         mAlertingNotificationManager.showNotification(mEntry);
 
-        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
         assertTrue(mAlertingNotificationManager.hasNotifications());
-        assertEquals(mEntry, mAlertingNotificationManager.getEntry(mEntry.key));
+        assertEquals(mEntry, mAlertingNotificationManager.getEntry(mEntry.getKey()));
     }
 
     @Test
@@ -155,7 +155,7 @@
         TestableLooper.get(this).processMessages(1);
 
         assertFalse("Test timed out", mTimedOut);
-        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
@@ -163,9 +163,10 @@
         mAlertingNotificationManager.showNotification(mEntry);
 
         // Try to remove but defer, since the notification has not been shown long enough.
-        mAlertingNotificationManager.removeNotification(mEntry.key, false /* releaseImmediately */);
+        mAlertingNotificationManager.removeNotification(
+                mEntry.getKey(), false /* releaseImmediately */);
 
-        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertTrue(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
@@ -173,9 +174,10 @@
         mAlertingNotificationManager.showNotification(mEntry);
 
         // Remove forcibly with releaseImmediately = true.
-        mAlertingNotificationManager.removeNotification(mEntry.key, true /* releaseImmediately */);
+        mAlertingNotificationManager.removeNotification(
+                mEntry.getKey(), true /* releaseImmediately */);
 
-        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.key));
+        assertFalse(mAlertingNotificationManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
@@ -199,7 +201,7 @@
         mAlertingNotificationManager.showNotification(mEntry);
 
         // The entry has just been added so we should not remove immediately.
-        assertFalse(mAlertingNotificationManager.canRemoveImmediately(mEntry.key));
+        assertFalse(mAlertingNotificationManager.canRemoveImmediately(mEntry.getKey()));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 1bd01e1..8c9ae71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -15,6 +15,8 @@
 package com.android.systemui.statusbar;
 
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Matchers.eq;
@@ -25,10 +27,12 @@
 import android.content.ComponentName;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.view.WindowInsetsController.Appearance;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 
@@ -110,21 +114,56 @@
     }
 
     @Test
-    public void testSetSystemUiVisibility() {
-        Rect r = new Rect();
-        mCommandQueue.setSystemUiVisibility(DEFAULT_DISPLAY, 1, 2, 3, 4, null, r, false);
-        waitForIdleSync();
-        verify(mCallbacks).setSystemUiVisibility(eq(DEFAULT_DISPLAY), eq(1), eq(2), eq(3), eq(4),
-                eq(null), eq(r), eq(false));
+    public void testOnSystemBarAppearanceChanged() {
+        doTestOnSystemBarAppearanceChanged(DEFAULT_DISPLAY, 1,
+                new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false);
     }
 
     @Test
-    public void testSetSystemUiVisibilityForSecondaryDisplay() {
-        Rect r = new Rect();
-        mCommandQueue.setSystemUiVisibility(SECONDARY_DISPLAY, 1, 2, 3, 4, null, r, false);
+    public void testOnSystemBarAppearanceChangedForSecondaryDisplay() {
+        doTestOnSystemBarAppearanceChanged(SECONDARY_DISPLAY, 1,
+                new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false);
+    }
+
+    private void doTestOnSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+            AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+        mCommandQueue.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
+                navbarColorManagedByIme);
         waitForIdleSync();
-        verify(mCallbacks).setSystemUiVisibility(eq(SECONDARY_DISPLAY), eq(1), eq(2), eq(3), eq(4),
-                eq(null), eq(r), eq(false));
+        verify(mCallbacks).onSystemBarAppearanceChanged(eq(displayId), eq(appearance),
+                eq(appearanceRegions), eq(navbarColorManagedByIme));
+    }
+
+    @Test
+    public void testShowTransient() {
+        int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+        mCommandQueue.showTransient(DEFAULT_DISPLAY, types);
+        waitForIdleSync();
+        verify(mCallbacks).showTransient(eq(DEFAULT_DISPLAY), eq(types));
+    }
+
+    @Test
+    public void testShowTransientForSecondaryDisplay() {
+        int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+        mCommandQueue.showTransient(SECONDARY_DISPLAY, types);
+        waitForIdleSync();
+        verify(mCallbacks).showTransient(eq(SECONDARY_DISPLAY), eq(types));
+    }
+
+    @Test
+    public void testAbortTransient() {
+        int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+        mCommandQueue.abortTransient(DEFAULT_DISPLAY, types);
+        waitForIdleSync();
+        verify(mCallbacks).abortTransient(eq(DEFAULT_DISPLAY), eq(types));
+    }
+
+    @Test
+    public void testAbortTransientForSecondaryDisplay() {
+        int[] types = new int[]{ TYPE_TOP_BAR, TYPE_NAVIGATION_BAR };
+        mCommandQueue.abortTransient(SECONDARY_DISPLAY, types);
+        waitForIdleSync();
+        verify(mCallbacks).abortTransient(eq(SECONDARY_DISPLAY), eq(types));
     }
 
     @Test
@@ -379,10 +418,9 @@
 
     @Test
     public void testOnBiometricAuthenticated() {
-        String failureReason = "test_failure_reason";
-        mCommandQueue.onBiometricAuthenticated(true /* authenticated */, failureReason);
+        mCommandQueue.onBiometricAuthenticated();
         waitForIdleSync();
-        verify(mCallbacks).onBiometricAuthenticated(eq(true), eq(failureReason));
+        verify(mCallbacks).onBiometricAuthenticated();
     }
 
     @Test
@@ -395,11 +433,12 @@
 
     @Test
     public void testOnBiometricError() {
-        final int errorCode = 1;
-        String errorMessage = "test_error_message";
-        mCommandQueue.onBiometricError(errorCode, errorMessage);
+        final int modality = 1;
+        final int error = 2;
+        final int vendorCode = 3;
+        mCommandQueue.onBiometricError(modality, error, vendorCode);
         waitForIdleSync();
-        verify(mCallbacks).onBiometricError(eq(errorCode), eq(errorMessage));
+        verify(mCallbacks).onBiometricError(eq(modality), eq(error), eq(vendorCode));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java
index 33b0d2c..2420e57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryHelper.java
@@ -36,7 +36,7 @@
         private final NotificationEntry mTarget;
 
         private ModifiedRankingBuilder(NotificationEntry target) {
-            super(target.ranking());
+            super(target.getRanking());
             mTarget = target;
         }
 
@@ -52,14 +52,14 @@
         private final NotificationEntry mTarget;
 
         private ModifiedSbnBuilder(NotificationEntry target) {
-            super(target.sbn());
+            super(target.getSbn());
             mTarget = target;
         }
 
         @Override
         public StatusBarNotification build() {
             final StatusBarNotification sbn = super.build();
-            mTarget.setNotification(sbn);
+            mTarget.setSbn(sbn);
             return sbn;
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
index 28a7e40..9b860c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
@@ -523,7 +523,7 @@
         modifyRanking(entry)
                 .setCanBubble(true)
                 .build();
-        entry.sbn().getNotification().flags |= FLAG_BUBBLE;
+        entry.getSbn().getNotification().flags |= FLAG_BUBBLE;
 
         assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(entry)).isFalse();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 852ddb2..2514c93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -97,7 +97,7 @@
     @Test
     public void testPerformOnRemoveNotification() {
         when(mController.isRemoteInputActive(mEntry)).thenReturn(true);
-        mRemoteInputManager.onPerformRemoveNotification(mEntry, mEntry.key());
+        mRemoteInputManager.onPerformRemoveNotification(mEntry, mEntry.getKey());
 
         verify(mController).removeRemoteInput(mEntry, null);
     }
@@ -112,7 +112,7 @@
     @Test
     public void testShouldExtendLifetime_isSpinning() {
         NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
-        when(mController.isSpinning(mEntry.key)).thenReturn(true);
+        when(mController.isSpinning(mEntry.getKey())).thenReturn(true);
 
         assertTrue(mRemoteInputHistoryExtender.shouldExtendLifetime(mEntry));
     }
@@ -128,7 +128,7 @@
     @Test
     public void testShouldExtendLifetime_smartReplySending() {
         NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY = true;
-        when(mSmartReplyController.isSendingSmartReply(mEntry.key)).thenReturn(true);
+        when(mSmartReplyController.isSendingSmartReply(mEntry.getKey())).thenReturn(true);
 
         assertTrue(mSmartReplyHistoryExtender.shouldExtendLifetime(mEntry));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index cb4096c..90bd0e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -326,7 +326,7 @@
                 .build();
 
         entry.setRow(row);
-        entry.createIcons(mContext, entry.sbn());
+        entry.createIcons(mContext, entry.getSbn());
         row.setEntry(entry);
         row.getNotificationInflater().addInflationFlags(extraInflationFlags);
         NotificationContentInflaterTest.runThenWaitForInflation(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 6efa57d..18649bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -143,11 +143,11 @@
                 Lists.newArrayList(entry0, entry1, entry2));
 
         // Set up group manager to report that they should be bundled now.
-        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(true);
-        when(mGroupManager.isChildInGroupWithSummary(entry2.notification)).thenReturn(true);
-        when(mGroupManager.getGroupSummary(entry1.notification)).thenReturn(entry0);
-        when(mGroupManager.getGroupSummary(entry2.notification)).thenReturn(entry0);
+        when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(true);
+        when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(true);
+        when(mGroupManager.getGroupSummary(entry1.getSbn())).thenReturn(entry0);
+        when(mGroupManager.getGroupSummary(entry2.getSbn())).thenReturn(entry0);
 
         // Run updateNotifications - the view hierarchy should be reorganized.
         mViewHierarchyManager.updateNotificationViews();
@@ -172,9 +172,9 @@
                 Lists.newArrayList(entry0, entry1, entry2));
 
         // Set up group manager to report that they should not be bundled now.
-        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry2.notification)).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(false);
 
         // Run updateNotifications - the view hierarchy should be reorganized.
         mViewHierarchyManager.updateNotificationViews();
@@ -201,9 +201,9 @@
                 Lists.newArrayList(entry0, entry1));
 
         // Set up group manager to report a suppressed summary now.
-        when(mGroupManager.isChildInGroupWithSummary(entry0.notification)).thenReturn(false);
-        when(mGroupManager.isChildInGroupWithSummary(entry1.notification)).thenReturn(false);
-        when(mGroupManager.isSummaryOfSuppressedGroup(entry0.notification)).thenReturn(true);
+        when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false);
+        when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false);
+        when(mGroupManager.isSummaryOfSuppressedGroup(entry0.getSbn())).thenReturn(true);
 
         // Run updateNotifications - the view hierarchy should be reorganized.
         mViewHierarchyManager.updateNotificationViews();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index e52a258..b2a5109 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -82,6 +82,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -139,6 +140,7 @@
     @Mock private RowInflaterTask mAsyncInflationTask;
     @Mock private NotificationRowBinder mMockedRowBinder;
 
+    private int mId;
     private NotificationEntry mEntry;
     private StatusBarNotification mSbn;
     private TestableNotificationEntryManager mEntryManager;
@@ -148,8 +150,12 @@
         private final CountDownLatch mCountDownLatch;
 
         TestableNotificationEntryManager() {
-            super(new NotificationData(mock(NotificationSectionsFeatureManager.class),
-                    mock(NotifLog.class)), mock(NotifLog.class));
+            super(
+                    new NotificationData(
+                            mock(NotificationSectionsFeatureManager.class),
+                            mock(NotifLog.class),
+                            mock(PeopleNotificationIdentifier.class)),
+                    mock(NotifLog.class));
             mCountDownLatch = new CountDownLatch(1);
         }
 
@@ -238,19 +244,8 @@
         when(mListContainer.getViewParentForNotification(any())).thenReturn(
                 new FrameLayout(mContext));
 
-        Notification.Builder n = new Notification.Builder(mContext, "")
-                .setSmallIcon(R.drawable.ic_person)
-                .setContentTitle("Title")
-                .setContentText("Text");
-
-        mEntry = new NotificationEntryBuilder()
-                .setPkg(TEST_PACKAGE_NAME)
-                .setOpPkg(TEST_PACKAGE_NAME)
-                .setUid(TEST_UID)
-                .setNotification(n.build())
-                .setUser(new UserHandle(ActivityManager.getCurrentUser()))
-                .build();
-        mSbn = mEntry.sbn();
+        mEntry = createNotification();
+        mSbn = mEntry.getSbn();
 
         mEntry.expandedIcon = mock(StatusBarIconView.class);
 
@@ -270,7 +265,8 @@
         notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
         mEntryManager.setRowBinder(notificationRowBinder);
 
-        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
+        setUserSentiment(
+                mEntry.getKey(), NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
     @Test
@@ -317,7 +313,8 @@
 
         mEntryManager.getNotificationData().add(mEntry);
 
-        setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
+        setUserSentiment(
+                mEntry.getKey(), NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
 
         mEntryManager.updateNotification(mSbn, mRankingMap);
         TestableLooper.get(this).processMessages(1);
@@ -341,7 +338,7 @@
         TestableLooper.get(this).processAllMessages();
 
         NotificationData notifData = mock(NotificationData.class);
-        when(notifData.get(mEntry.key)).thenReturn(mEntry);
+        when(notifData.get(mEntry.getKey())).thenReturn(mEntry);
 
         mEntryManager.setNotificationData(notifData);
 
@@ -413,7 +410,7 @@
         mEntry.setRow(mRow);
         mEntry.setInflationTask(mAsyncInflationTask);
         mEntryManager.getNotificationData().add(mEntry);
-        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+        setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow).setEntry(eq(mEntry));
@@ -429,7 +426,7 @@
 
         mEntry.setRow(mRow);
         mEntryManager.getNotificationData().add(mEntry);
-        setSmartActions(mEntry.key, null);
+        setSmartActions(mEntry.getKey(), null);
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
@@ -443,7 +440,7 @@
 
         mEntry.setRow(null);
         mEntryManager.getNotificationData().add(mEntry);
-        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+        setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
@@ -457,8 +454,8 @@
         when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
 
         mEntry.setRow(null);
-        mEntryManager.mPendingNotifications.put(mEntry.key, mEntry);
-        setSmartActions(mEntry.key, new ArrayList<>(Arrays.asList(createAction())));
+        mEntryManager.mPendingNotifications.put(mEntry.getKey(), mEntry);
+        setSmartActions(mEntry.getKey(), new ArrayList<>(Arrays.asList(createAction())));
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
@@ -478,7 +475,7 @@
         mEntryManager.addNotificationLifetimeExtender(extender);
 
         // WHEN the notification is removed
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the extender is asked to manage the lifetime
         verify(extender).setShouldManageLifetime(mEntry, true);
@@ -494,12 +491,12 @@
         mEntryManager.getNotificationData().add(mEntry);
         final FakeNotificationLifetimeExtender extender = new FakeNotificationLifetimeExtender();
         mEntryManager.addNotificationLifetimeExtender(extender);
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
-        assertTrue(extender.isManaging(mEntry.key));
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
+        assertTrue(extender.isManaging(mEntry.getKey()));
 
         // WHEN the extender finishes its extension
         extender.setExtendLifetimes(false);
-        extender.getCallback().onSafeToRemove(mEntry.key);
+        extender.getCallback().onSafeToRemove(mEntry.getKey());
 
         // THEN the notification is removed
         assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
@@ -514,10 +511,10 @@
         NotificationLifetimeExtender extender = mock(NotificationLifetimeExtender.class);
         when(extender.shouldExtendLifetime(mEntry)).thenReturn(true);
         mEntryManager.addNotificationLifetimeExtender(extender);
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // WHEN the notification is updated
-        mEntryManager.updateNotification(mEntry.notification, mRankingMap);
+        mEntryManager.updateNotification(mEntry.getSbn(), mRankingMap);
 
         // THEN the lifetime extension is canceled
         verify(extender).setShouldManageLifetime(mEntry, false);
@@ -539,13 +536,13 @@
         mEntryManager.addNotificationLifetimeExtender(extender2);
 
         // GIVEN a notification was lifetime-extended and extender2 is managing it
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
         verify(extender1, never()).setShouldManageLifetime(mEntry, true);
         verify(extender2).setShouldManageLifetime(mEntry, true);
 
         // WHEN the extender1 changes its mind and wants to extend the lifetime of the notif
         when(extender1.shouldExtendLifetime(mEntry)).thenReturn(true);
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN extender2 stops managing the notif and extender1 starts managing it
         verify(extender1).setShouldManageLifetime(mEntry, true);
@@ -569,14 +566,14 @@
         mEntryManager.getNotificationData().add(mEntry);
 
         // GIVEN interceptor that intercepts that entry
-        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.key), anyInt()))
+        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.getKey()), anyInt()))
                 .thenReturn(true);
 
         // WHEN the notification is removed
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the interceptor intercepts & the entry is not removed & no listeners are called
-        assertNotNull(mEntryManager.getNotificationData().get(mEntry.key));
+        assertNotNull(mEntryManager.getNotificationData().get(mEntry.getKey()));
         verify(mEntryListener, never()).onEntryRemoved(eq(mEntry),
                 any(NotificationVisibility.class), anyBoolean());
     }
@@ -588,18 +585,34 @@
         mEntryManager.getNotificationData().add(mEntry);
 
         // GIVEN interceptor that doesn't intercept
-        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.key), anyInt()))
+        when(mRemoveInterceptor.onNotificationRemoveRequested(eq(mEntry.getKey()), anyInt()))
                 .thenReturn(false);
 
         // WHEN the notification is removed
-        mEntryManager.removeNotification(mEntry.key, mRankingMap, UNDEFINED_DISMISS_REASON);
+        mEntryManager.removeNotification(mEntry.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
         // THEN the interceptor intercepts & the entry is not removed & no listeners are called
-        assertNull(mEntryManager.getNotificationData().get(mEntry.key));
+        assertNull(mEntryManager.getNotificationData().get(mEntry.getKey()));
         verify(mEntryListener, atLeastOnce()).onEntryRemoved(eq(mEntry),
                 any(NotificationVisibility.class), anyBoolean());
     }
 
+    private NotificationEntry createNotification() {
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+
+        return new NotificationEntryBuilder()
+                .setPkg(TEST_PACKAGE_NAME)
+                .setOpPkg(TEST_PACKAGE_NAME)
+                .setUid(TEST_UID)
+                .setId(mId++)
+                .setNotification(n.build())
+                .setUser(new UserHandle(ActivityManager.getCurrentUser()))
+                .build();
+    }
+
     private Notification.Action createAction() {
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
@@ -626,17 +639,17 @@
         public void setShouldManageLifetime(
                 @NonNull NotificationEntry entry,
                 boolean shouldManage) {
-            final boolean hasEntry = mManagedNotifs.contains(entry.key);
+            final boolean hasEntry = mManagedNotifs.contains(entry.getKey());
             if (shouldManage) {
                 if (hasEntry) {
-                    throw new RuntimeException("Already managing this entry: " + entry.key);
+                    throw new RuntimeException("Already managing this entry: " + entry.getKey());
                 }
-                mManagedNotifs.add(entry.key);
+                mManagedNotifs.add(entry.getKey());
             } else {
                 if (!hasEntry) {
-                    throw new RuntimeException("Not managing this entry: " + entry.key);
+                    throw new RuntimeException("Not managing this entry: " + entry.getKey());
                 }
-                mManagedNotifs.remove(entry.key);
+                mManagedNotifs.remove(entry.getKey());
             }
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 45e1721..d85f275 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -142,7 +142,7 @@
     public void testSuppressSystemAlertNotification() {
         when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
         when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
         Bundle bundle = new Bundle();
         bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
         sbn.getNotification().extras = bundle;
@@ -152,7 +152,7 @@
 
     @Test
     public void testDoNotSuppressSystemAlertNotification() {
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
         Bundle bundle = new Bundle();
         bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
         sbn.getNotification().extras = bundle;
@@ -180,7 +180,7 @@
         // missing extra
         assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
 
-        StatusBarNotification sbn = mRow.getEntry().notification;
+        StatusBarNotification sbn = mRow.getEntry().getSbn();
         Bundle bundle = new Bundle();
         bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{});
         sbn.getNotification().extras = bundle;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
index 170c661..c2d2e31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
@@ -16,24 +16,16 @@
 
 package com.android.systemui.statusbar.notification;
 
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
-import android.app.AppOpsManager;
 import android.app.Notification;
 import android.os.UserHandle;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
 
@@ -46,6 +38,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -78,8 +71,10 @@
 
     // TODO: Remove this once EntryManager no longer needs to be mocked
     private NotificationData mNotificationData =
-            new NotificationData(new NotificationSectionsFeatureManager(
-                    new DeviceConfigProxyFake(), mContext), mock(NotifLog.class));
+            new NotificationData(
+                    new NotificationSectionsFeatureManager(new DeviceConfigProxyFake(), mContext),
+                    mock(NotifLog.class),
+                    mock(PeopleNotificationIdentifier.class));
 
     private int mNextNotifId = 0;
 
@@ -109,7 +104,7 @@
         final NotificationEntry entry = buildEntry();
         mEntryListener.onEntryRemoved(
                 entry,
-                NotificationVisibility.obtain(entry.key, 0, 0, true),
+                NotificationVisibility.obtain(entry.getKey(), 0, 0, true),
                 false);
         verify(mListContainer).cleanUpViewStateForEntry(entry);
     }
@@ -120,107 +115,6 @@
         verify(mEntryManager).updateNotifications(anyString());
     }
 
-    @Test
-    public void testAppOps_appOpAddedToForegroundNotif() {
-        // GIVEN a notification associated with a foreground service
-        final NotificationEntry entry = buildEntry();
-        mNotificationData.add(entry);
-        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
-                .thenReturn(entry.key);
-
-        // WHEN we are notified of a new app op
-        mController.updateNotificationsForAppOp(
-                AppOpsManager.OP_CAMERA,
-                entry.notification.getUid(),
-                entry.notification.getPackageName(),
-                true);
-
-        // THEN the app op is added to the entry
-        assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
-        // THEN updateNotifications(TEST) is called
-        verify(mEntryManager, times(1)).updateNotifications(anyString());
-    }
-
-    @Test
-    public void testAppOps_appOpAddedToUnrelatedNotif() {
-        // GIVEN No current foreground notifs
-        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
-                .thenReturn(null);
-
-        // WHEN An unrelated notification gets a new app op
-        mController.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
-
-        // THEN We never call updateNotifications(TEST)
-        verify(mEntryManager, never()).updateNotifications(anyString());
-    }
-
-    @Test
-    public void testAppOps_addNotificationWithExistingAppOps() {
-        // GIVEN a notification with three associated app ops that is associated with a foreground
-        // service
-        final NotificationEntry entry = buildEntry();
-        mNotificationData.add(entry);
-        ArraySet<Integer> expected = new ArraySet<>();
-        expected.add(3);
-        expected.add(235);
-        expected.add(1);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(entry.key);
-        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(expected);
-
-        // WHEN the notification is added
-        mEntryListener.onBeforeNotificationAdded(entry);
-
-        // THEN the entry is tagged with all three app ops
-        assertEquals(expected.size(), entry.mActiveAppOps.size());
-        for (int op : expected) {
-            assertTrue("Entry missing op " + op, entry.mActiveAppOps.contains(op));
-        }
-    }
-
-    @Test
-    public void testAdd_addNotificationWithNoExistingAppOps() {
-        // GIVEN a notification with NO associated app ops
-        final NotificationEntry entry = buildEntry();
-
-        mNotificationData.add(entry);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(entry.key);
-        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(null);
-
-        // WHEN the notification is added
-        mEntryListener.onBeforeNotificationAdded(entry);
-
-        // THEN the entry doesn't have any app ops associated with it
-        assertEquals(0, entry.mActiveAppOps.size());
-    }
-
-    @Test
-    public void testAdd_addNonForegroundNotificationWithExistingAppOps() {
-        // GIVEN a notification with app ops that isn't associated with a foreground service
-        final NotificationEntry entry = buildEntry();
-        mNotificationData.add(entry);
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(3);
-        ops.add(235);
-        ops.add(1);
-        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn(ops);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                entry.notification.getUserId(),
-                entry.notification.getPackageName())).thenReturn("something else");
-
-        // WHEN the notification is added
-        mEntryListener.onBeforeNotificationAdded(entry);
-
-        // THEN the entry doesn't have any app ops associated with it
-        assertEquals(0, entry.mActiveAppOps.size());
-    }
-
     private NotificationEntry buildEntry() {
         mNextNotifId++;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
new file mode 100644
index 0000000..e1beb34
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -0,0 +1,625 @@
+/*
+ * 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.systemui.statusbar.notification.collection;
+
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.NotificationStats;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.ArrayMap;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.util.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import java.util.Arrays;
+import java.util.Map;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotifCollectionTest extends SysuiTestCase {
+
+    @Mock private IStatusBarService mStatusBarService;
+    @Mock private NotificationListener mListenerService;
+    @Spy private RecordingCollectionListener mCollectionListener;
+
+    @Spy private RecordingLifetimeExtender mExtender1 = new RecordingLifetimeExtender("Extender1");
+    @Spy private RecordingLifetimeExtender mExtender2 = new RecordingLifetimeExtender("Extender2");
+    @Spy private RecordingLifetimeExtender mExtender3 = new RecordingLifetimeExtender("Extender3");
+
+    @Captor private ArgumentCaptor<NotifServiceListener> mListenerCaptor;
+    @Captor private ArgumentCaptor<NotificationEntry> mEntryCaptor;
+
+    private NotifCollection mCollection;
+    private NotifServiceListener mServiceListener;
+
+    private NoManSimulator mNoMan;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+
+        mCollection = new NotifCollection(mStatusBarService);
+        mCollection.attach(mListenerService);
+        mCollection.addCollectionListener(mCollectionListener);
+
+        // Capture the listener object that the collection registers with the listener service so
+        // we can simulate listener service events in tests below
+        verify(mListenerService).setDownstreamListener(mListenerCaptor.capture());
+        mServiceListener = checkNotNull(mListenerCaptor.getValue());
+
+        mNoMan = new NoManSimulator(mServiceListener);
+    }
+
+    @Test
+    public void testEventDispatchedWhenNotifPosted() {
+        // WHEN a notification is posted
+        PostedNotif notif1 = mNoMan.postNotif(
+                buildNotif(TEST_PACKAGE, 3)
+                        .setRank(4747));
+
+        // THEN the listener is notified
+        verify(mCollectionListener).onEntryAdded(mEntryCaptor.capture());
+
+        NotificationEntry entry = mEntryCaptor.getValue();
+        assertEquals(notif1.key, entry.getKey());
+        assertEquals(notif1.sbn, entry.getSbn());
+        assertEquals(notif1.ranking, entry.getRanking());
+    }
+
+    @Test
+    public void testEventDispatchedWhenNotifUpdated() {
+        // GIVEN a collection with one notif
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(4747));
+
+        // WHEN the notif is reposted
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(89));
+
+        // THEN the listener is notified
+        verify(mCollectionListener).onEntryUpdated(mEntryCaptor.capture());
+
+        NotificationEntry entry = mEntryCaptor.getValue();
+        assertEquals(notif2.key, entry.getKey());
+        assertEquals(notif2.sbn, entry.getSbn());
+        assertEquals(notif2.ranking, entry.getRanking());
+    }
+
+    @Test
+    public void testEventDispatchedWhenNotifRemoved() {
+        // GIVEN a collection with one notif
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
+        clearInvocations(mCollectionListener);
+
+        PostedNotif notif = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        NotificationEntry entry = mCollectionListener.getEntry(notif.key);
+        clearInvocations(mCollectionListener);
+
+        // WHEN a notif is retracted
+        mNoMan.retractNotif(notif.sbn, REASON_APP_CANCEL);
+
+        // THEN the listener is notified
+        verify(mCollectionListener).onEntryRemoved(entry, REASON_APP_CANCEL, false);
+        assertEquals(notif.sbn, entry.getSbn());
+        assertEquals(notif.ranking, entry.getRanking());
+    }
+
+    @Test
+    public void testRankingsAreUpdatedForOtherNotifs() {
+        // GIVEN a collection with one notif
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(47));
+        NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
+
+        // WHEN a new notif is posted, triggering a rerank
+        mNoMan.setRanking(notif1.sbn.getKey(), new RankingBuilder(notif1.ranking)
+                .setRank(56)
+                .build());
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 77));
+
+        // THEN the ranking is updated on the first entry
+        assertEquals(56, entry1.getRanking().getRank());
+    }
+
+    @Test
+    public void testRankingUpdateIsProperlyIssuedToEveryone() {
+        // GIVEN a collection with a couple notifs
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+                .setRank(3));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 8)
+                .setRank(2));
+        PostedNotif notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 77)
+                .setRank(1));
+
+        NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+        NotificationEntry entry3 = mCollectionListener.getEntry(notif3.key);
+
+        // WHEN a ranking update is delivered
+        Ranking newRanking1 = new RankingBuilder(notif1.ranking)
+                .setRank(4)
+                .setExplanation("Foo bar")
+                .build();
+        Ranking newRanking2 = new RankingBuilder(notif2.ranking)
+                .setRank(5)
+                .setExplanation("baz buzz")
+                .build();
+        Ranking newRanking3 = new RankingBuilder(notif3.ranking)
+                .setRank(6)
+                .setExplanation("Penguin pizza")
+                .build();
+
+        mNoMan.setRanking(notif1.sbn.getKey(), newRanking1);
+        mNoMan.setRanking(notif2.sbn.getKey(), newRanking2);
+        mNoMan.setRanking(notif3.sbn.getKey(), newRanking3);
+        mNoMan.issueRankingUpdate();
+
+        // THEN all of the NotifEntries have their rankings properly updated
+        assertEquals(newRanking1, entry1.getRanking());
+        assertEquals(newRanking2, entry2.getRanking());
+        assertEquals(newRanking3, entry3.getRanking());
+    }
+
+    @Test
+    public void testNotifEntriesAreNotPersistedAcrossRemovalAndReposting() {
+        // GIVEN a notification that has been posted
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
+        NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
+
+        // WHEN the notification is retracted and then reposted
+        mNoMan.retractNotif(notif1.sbn, REASON_APP_CANCEL);
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
+
+        // THEN the new NotificationEntry is a new object
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif1.key);
+        assertNotEquals(entry2, entry1);
+    }
+
+    @Test
+    public void testDismissNotification() throws RemoteException {
+        // GIVEN a collection with a couple notifications and a lifetime extender
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88, "barTag"));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // WHEN a notification is manually dismissed
+        DismissedByUserStats stats = new DismissedByUserStats(
+                NotificationStats.DISMISSAL_SHADE,
+                NotificationStats.DISMISS_SENTIMENT_NEUTRAL,
+                NotificationVisibility.obtain(entry2.getKey(), 7, 2, true));
+
+        mCollection.dismissNotification(entry2, REASON_CLICK, stats);
+
+        // THEN we check for lifetime extension
+        verify(mExtender1).shouldExtendLifetime(entry2, REASON_CLICK);
+
+        // THEN we send the dismissal to system server
+        verify(mStatusBarService).onNotificationClear(
+                notif2.sbn.getPackageName(),
+                notif2.sbn.getTag(),
+                88,
+                notif2.sbn.getUser().getIdentifier(),
+                notif2.sbn.getKey(),
+                stats.dismissalSurface,
+                stats.dismissalSentiment,
+                stats.notificationVisibility);
+
+        // THEN we fire a remove event
+        verify(mCollectionListener).onEntryRemoved(entry2, REASON_CLICK, true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testDismissingNonExistentNotificationThrows() {
+        // GIVEN a collection that originally had three notifs, but where one was dismissed
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        PostedNotif notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 99));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+
+        // WHEN we try to dismiss a notification that isn't present
+        mCollection.dismissNotification(
+                entry2,
+                REASON_CLICK,
+                new DismissedByUserStats(0, 0, NotificationVisibility.obtain("foo", 47, 3, true)));
+
+        // THEN an exception is thrown
+    }
+
+    @Test
+    public void testLifetimeExtendersAreQueriedWhenNotifRemoved() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // WHEN a notification is removed
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+
+        // THEN each extender is asked whether to extend, even if earlier ones return true
+        verify(mExtender1).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender2).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+
+        // THEN the entry is not removed
+        assertTrue(mCollection.getNotifs().contains(entry2));
+
+        // THEN the entry properly records all extenders that returned true
+        assertEquals(Arrays.asList(mExtender1, mExtender2), entry2.mLifetimeExtenders);
+    }
+
+    @Test
+    public void testWhenLastLifetimeExtenderExpiresAllAreReQueried() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by one of them
+        mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN the last active extender expires (but new ones become active)
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = false;
+        mExtender3.shouldExtendLifetime = true;
+        mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+
+        // THEN each extender is re-queried
+        verify(mExtender1).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender2).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+        verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
+
+        // THEN the entry is not removed
+        assertTrue(mCollection.getNotifs().contains(entry2));
+
+        // THEN the entry properly records all extenders that returned true
+        assertEquals(Arrays.asList(mExtender1, mExtender3), entry2.mLifetimeExtenders);
+    }
+
+    @Test
+    public void testExtendersAreNotReQueriedUntilFinalActiveExtenderExpires() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN one (but not all) of the extenders expires
+        mExtender2.shouldExtendLifetime = false;
+        mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+
+        // THEN the entry is not removed
+        assertTrue(mCollection.getNotifs().contains(entry2));
+
+        // THEN we don't re-query the extenders
+        verify(mExtender1, never()).shouldExtendLifetime(eq(entry2), anyInt());
+        verify(mExtender2, never()).shouldExtendLifetime(eq(entry2), anyInt());
+        verify(mExtender3, never()).shouldExtendLifetime(eq(entry2), anyInt());
+
+        // THEN the entry properly records all extenders that returned true
+        assertEquals(Arrays.asList(mExtender1), entry2.mLifetimeExtenders);
+    }
+
+    @Test
+    public void testNotificationIsRemovedWhenAllLifetimeExtendersExpire() {
+        // GIVEN a couple notifications and a few lifetime extenders
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN all of the active extenders expire
+        mExtender2.shouldExtendLifetime = false;
+        mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+        mExtender1.shouldExtendLifetime = false;
+        mExtender1.callback.onEndLifetimeExtension(mExtender1, entry2);
+
+        // THEN the entry removed
+        assertFalse(mCollection.getNotifs().contains(entry2));
+        verify(mCollectionListener).onEntryRemoved(entry2, REASON_UNKNOWN, false);
+    }
+
+    @Test
+    public void testLifetimeExtensionIsCanceledWhenNotifIsUpdated() {
+        // GIVEN a few lifetime extenders and a couple notifications
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN the notification is reposted
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+
+        // THEN all of the active lifetime extenders are canceled
+        verify(mExtender1).cancelLifetimeExtension(entry2);
+        verify(mExtender2).cancelLifetimeExtension(entry2);
+
+        // THEN the notification is still present
+        assertTrue(mCollection.getNotifs().contains(entry2));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testReentrantCallsToLifetimeExtendersThrow() {
+        // GIVEN a few lifetime extenders and a couple notifications
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN a lifetime extender makes a reentrant call during cancelLifetimeExtension()
+        mExtender2.onCancelLifetimeExtension = () -> {
+            mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
+        };
+        // This triggers the call to cancelLifetimeExtension()
+        mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+
+        // THEN an exception is thrown
+    }
+
+    @Test
+    public void testRankingIsUpdatedWhenALifetimeExtendedNotifIsReposted() {
+        // GIVEN a few lifetime extenders and a couple notifications
+        mCollection.addNotificationLifetimeExtender(mExtender1);
+        mCollection.addNotificationLifetimeExtender(mExtender2);
+        mCollection.addNotificationLifetimeExtender(mExtender3);
+
+        mExtender1.shouldExtendLifetime = true;
+        mExtender2.shouldExtendLifetime = true;
+
+        PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+        PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
+
+        // GIVEN a notification gets lifetime-extended by a couple of them
+        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
+        assertTrue(mCollection.getNotifs().contains(entry2));
+        clearInvocations(mExtender1, mExtender2, mExtender3);
+
+        // WHEN the notification is reposted
+        PostedNotif notif2a = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88)
+                .setRank(4747)
+                .setExplanation("Some new explanation"));
+
+        // THEN the notification's ranking is properly updated
+        assertEquals(notif2a.ranking, entry2.getRanking());
+    }
+
+    private static NotificationEntryBuilder buildNotif(String pkg, int id, String tag) {
+        return new NotificationEntryBuilder()
+                .setPkg(pkg)
+                .setId(id)
+                .setTag(tag);
+    }
+
+    private static NotificationEntryBuilder buildNotif(String pkg, int id) {
+        return new NotificationEntryBuilder()
+                .setPkg(pkg)
+                .setId(id);
+    }
+
+    private static class NoManSimulator {
+        private final NotifServiceListener mListener;
+        private final Map<String, Ranking> mRankings = new ArrayMap<>();
+
+        private NoManSimulator(
+                NotifServiceListener listener) {
+            mListener = listener;
+        }
+
+        PostedNotif postNotif(NotificationEntryBuilder builder) {
+            NotificationEntry entry = builder.build();
+            mRankings.put(entry.getKey(), entry.getRanking());
+            mListener.onNotificationPosted(entry.getSbn(), buildRankingMap());
+            return new PostedNotif(entry.getSbn(), entry.getRanking());
+        }
+
+        void retractNotif(StatusBarNotification sbn, int reason) {
+            assertNotNull(mRankings.remove(sbn.getKey()));
+            mListener.onNotificationRemoved(sbn, buildRankingMap(), reason);
+        }
+
+        void issueRankingUpdate() {
+            mListener.onNotificationRankingUpdate(buildRankingMap());
+        }
+
+        void setRanking(String key, Ranking ranking) {
+            mRankings.put(key, ranking);
+        }
+
+        private RankingMap buildRankingMap() {
+            return new RankingMap(mRankings.values().toArray(new Ranking[0]));
+        }
+    }
+
+    private static class PostedNotif {
+        public final String key;
+        public final StatusBarNotification sbn;
+        public final Ranking ranking;
+
+        private PostedNotif(StatusBarNotification sbn,
+                Ranking ranking) {
+            this.key = sbn.getKey();
+            this.sbn = sbn;
+            this.ranking = ranking;
+        }
+    }
+
+    private static class RecordingCollectionListener implements NotifCollectionListener {
+        private final Map<String, NotificationEntry> mLastSeenEntries = new ArrayMap<>();
+
+        @Override
+        public void onEntryAdded(NotificationEntry entry) {
+            mLastSeenEntries.put(entry.getKey(), entry);
+        }
+
+        @Override
+        public void onEntryUpdated(NotificationEntry entry) {
+        }
+
+        @Override
+        public void onEntryRemoved(NotificationEntry entry, int reason, boolean removedByUser) {
+        }
+
+        public NotificationEntry getEntry(String key) {
+            if (!mLastSeenEntries.containsKey(key)) {
+                throw new RuntimeException("Key not found: " + key);
+            }
+            return mLastSeenEntries.get(key);
+        }
+    }
+
+    private static class RecordingLifetimeExtender implements NotifLifetimeExtender {
+        private final String mName;
+
+        public @Nullable OnEndLifetimeExtensionCallback callback;
+        public boolean shouldExtendLifetime = false;
+        public @Nullable Runnable onCancelLifetimeExtension;
+
+        private RecordingLifetimeExtender(String name) {
+            mName = name;
+        }
+
+        @Override
+        public String getName() {
+            return mName;
+        }
+
+        @Override
+        public void setCallback(OnEndLifetimeExtensionCallback callback) {
+            this.callback = callback;
+        }
+
+        @Override
+        public boolean shouldExtendLifetime(
+                NotificationEntry entry,
+                @CancellationReason int reason) {
+            return shouldExtendLifetime;
+        }
+
+        @Override
+        public void cancelLifetimeExtension(NotificationEntry entry) {
+            if (onCancelLifetimeExtension != null) {
+                onCancelLifetimeExtension.run();
+            }
+        }
+    }
+
+    private static final String TEST_PACKAGE = "com.android.test.collection";
+    private static final String TEST_PACKAGE2 = "com.android.test.collection2";
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
index 1be6f61..1a469d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.notification.collection;
 
-import static android.app.AppOpsManager.OP_ACCEPT_HANDOVER;
-import static android.app.AppOpsManager.OP_CAMERA;
 import static android.app.Notification.CATEGORY_ALARM;
 import static android.app.Notification.CATEGORY_CALL;
 import static android.app.Notification.CATEGORY_EVENT;
@@ -56,7 +54,6 @@
 import android.graphics.drawable.Icon;
 import android.media.session.MediaSession;
 import android.os.Bundle;
-import android.os.Process;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.SnoozeCriterion;
@@ -64,7 +61,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
-import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
 
@@ -81,6 +77,7 @@
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ShadeController;
@@ -153,75 +150,12 @@
     public void testChannelSetWhenAdded() {
         Bundle override = new Bundle();
         override.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
-        mNotificationData.rankingOverrides.put(mRow.getEntry().key, override);
+        mNotificationData.rankingOverrides.put(mRow.getEntry().getKey(), override);
         mNotificationData.add(mRow.getEntry());
         assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().getChannel());
     }
 
     @Test
-    public void testAllRelevantNotisTaggedWithAppOps() throws Exception {
-        mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
-                .createRow();
-        mNotificationData.add(row2.getEntry());
-        ExpandableNotificationRow diffPkg =
-                new NotificationTestHelper(getContext(), mDependency).createRow("pkg", 4000,
-                        Process.myUserHandle());
-        mNotificationData.add(diffPkg.getEntry());
-
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        expectedOps.add(OP_ACCEPT_HANDOVER);
-
-        for (int op : expectedOps) {
-            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, mRow.getEntry().key, true);
-            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, row2.getEntry().key, true);
-        }
-        for (int op : expectedOps) {
-            assertTrue(mRow.getEntry().key + " doesn't have op " + op,
-                    mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(op));
-            assertTrue(row2.getEntry().key + " doesn't have op " + op,
-                    mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(op));
-            assertFalse(diffPkg.getEntry().key + " has op " + op,
-                    mNotificationData.get(diffPkg.getEntry().key).mActiveAppOps.contains(op));
-        }
-    }
-
-    @Test
-    public void testAppOpsRemoval() throws Exception {
-        mNotificationData.add(mRow.getEntry());
-        ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
-                .createRow();
-        mNotificationData.add(row2.getEntry());
-
-        ArraySet<Integer> expectedOps = new ArraySet<>();
-        expectedOps.add(OP_CAMERA);
-        expectedOps.add(OP_ACCEPT_HANDOVER);
-
-        for (int op : expectedOps) {
-            mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
-                    NotificationTestHelper.PKG, row2.getEntry().key, true);
-        }
-
-        expectedOps.remove(OP_ACCEPT_HANDOVER);
-        mNotificationData.updateAppOp(OP_ACCEPT_HANDOVER, NotificationTestHelper.UID,
-                NotificationTestHelper.PKG, row2.getEntry().key, false);
-
-        assertTrue(mRow.getEntry().key + " doesn't have op " + OP_CAMERA,
-                mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
-        assertTrue(row2.getEntry().key + " doesn't have op " + OP_CAMERA,
-                mNotificationData.get(row2.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
-        assertFalse(mRow.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
-                mNotificationData.get(mRow.getEntry().key)
-                        .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
-        assertFalse(row2.getEntry().key + " has op " + OP_ACCEPT_HANDOVER,
-                mNotificationData.get(row2.getEntry().key)
-                        .mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
-    }
-
-    @Test
     public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications()
             throws Exception {
         mNotificationData.add(mRow.getEntry());
@@ -230,9 +164,9 @@
         mNotificationData.add(row2.getEntry());
 
         when(mEnvironment.isNotificationForCurrentProfiles(
-                mRow.getEntry().notification)).thenReturn(false);
+                mRow.getEntry().getSbn())).thenReturn(false);
         when(mEnvironment.isNotificationForCurrentProfiles(
-                row2.getEntry().notification)).thenReturn(true);
+                row2.getEntry().getSbn())).thenReturn(true);
         ArrayList<NotificationEntry> result =
                 mNotificationData.getNotificationsForCurrentUser();
 
@@ -244,12 +178,12 @@
     public void testIsExemptFromDndVisualSuppression_foreground() {
         initStatusBarNotification(false);
 
-        mEntry.sbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+        mEntry.getSbn().getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mEntry.setRow(mRow);
         mNotificationData.add(mEntry);
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.key, override);
+        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
 
         assertTrue(mEntry.isExemptFromDndVisualSuppression());
         assertFalse(mEntry.shouldSuppressAmbient());
@@ -258,7 +192,7 @@
     @Test
     public void testIsExemptFromDndVisualSuppression_media() {
         initStatusBarNotification(false);
-        Notification n = mEntry.sbn().getNotification();
+        Notification n = mEntry.getSbn().getNotification();
         Notification.Builder nb = Notification.Builder.recoverBuilder(mContext, n);
         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
         n = nb.build();
@@ -269,7 +203,7 @@
         mNotificationData.add(mEntry);
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.key, override);
+        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
 
         assertTrue(mEntry.isExemptFromDndVisualSuppression());
         assertFalse(mEntry.shouldSuppressAmbient());
@@ -283,7 +217,7 @@
         mNotificationData.add(mEntry);
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, 255);
-        mNotificationData.rankingOverrides.put(mEntry.key, override);
+        mNotificationData.rankingOverrides.put(mEntry.getKey(), override);
 
         assertTrue(mEntry.isExemptFromDndVisualSuppression());
         assertFalse(mEntry.shouldSuppressAmbient());
@@ -299,7 +233,7 @@
         entry.mIsSystemNotification = true;
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_VIS_EFFECTS, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
-        mNotificationData.rankingOverrides.put(entry.key, override);
+        mNotificationData.rankingOverrides.put(entry.getKey(), override);
         mNotificationData.add(entry);
 
         modifySbn(entry)
@@ -511,7 +445,7 @@
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         override.putInt(OVERRIDE_RANK, 1);
-        mNotificationData.rankingOverrides.put(a.key, override);
+        mNotificationData.rankingOverrides.put(a.getKey(), override);
 
         Notification bN = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.MessagingStyle(""))
@@ -530,7 +464,7 @@
         Bundle bOverride = new Bundle();
         bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         bOverride.putInt(OVERRIDE_RANK, 2);
-        mNotificationData.rankingOverrides.put(b.key, bOverride);
+        mNotificationData.rankingOverrides.put(b.getKey(), bOverride);
 
         assertEquals(1, mNotificationData.mRankingComparator.compare(a, b));
     }
@@ -555,7 +489,7 @@
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         override.putInt(OVERRIDE_RANK, 1);
-        mNotificationData.rankingOverrides.put(a.key, override);
+        mNotificationData.rankingOverrides.put(a.getKey(), override);
 
         Notification bN = new Notification.Builder(mContext, "test")
                 .setStyle(new Notification.MessagingStyle(""))
@@ -574,7 +508,7 @@
         Bundle bOverride = new Bundle();
         bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
         bOverride.putInt(OVERRIDE_RANK, 2);
-        mNotificationData.rankingOverrides.put(b.key, bOverride);
+        mNotificationData.rankingOverrides.put(b.getKey(), bOverride);
 
         assertEquals(-1, mNotificationData.mRankingComparator.compare(a, b));
     }
@@ -594,7 +528,7 @@
 
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_DEFAULT);
-        mNotificationData.rankingOverrides.put(entry.key(), override);
+        mNotificationData.rankingOverrides.put(entry.getKey(), override);
 
         entry.setRow(mRow);
         mNotificationData.add(entry);
@@ -618,7 +552,7 @@
 
         Bundle override = new Bundle();
         override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-        mNotificationData.rankingOverrides.put(entry.key(), override);
+        mNotificationData.rankingOverrides.put(entry.getKey(), override);
 
         entry.setRow(mRow);
         mNotificationData.add(entry);
@@ -639,7 +573,10 @@
 
     public static class TestableNotificationData extends NotificationData {
         public TestableNotificationData(NotificationSectionsFeatureManager sectionsFeatureManager) {
-            super(sectionsFeatureManager, mock(NotifLog.class));
+            super(
+                    sectionsFeatureManager,
+                    mock(NotifLog.class),
+                    mock(PeopleNotificationIdentifier.class));
         }
 
         public static final String OVERRIDE_RANK = "r";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 24cd056..47c17ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -113,7 +113,7 @@
     @Test
     public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception {
         NotificationVisibility[] newlyVisibleKeys = {
-                NotificationVisibility.obtain(mEntry.key, 0, 1, true)
+                NotificationVisibility.obtain(mEntry.getKey(), 0, 1, true)
         };
         NotificationVisibility[] noLongerVisibleKeys = {};
         doAnswer(invocation -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 41fe173..c7877bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -487,13 +487,13 @@
         NotificationEntry entry = createTestNotificationRow().getEntry();
         mGutsManager.setShouldManageLifetime(entry, true /* shouldManage */);
 
-        assertTrue(entry.key.equals(mGutsManager.mKeyToRemoveOnGutsClosed));
+        assertTrue(entry.getKey().equals(mGutsManager.mKeyToRemoveOnGutsClosed));
     }
 
     @Test
     public void testSetShouldManageLifetime_setShouldNotManage() {
         NotificationEntry entry = createTestNotificationRow().getEntry();
-        mGutsManager.mKeyToRemoveOnGutsClosed = entry.key;
+        mGutsManager.mKeyToRemoveOnGutsClosed = entry.getKey();
         mGutsManager.setShouldManageLifetime(entry, false /* shouldManage */);
 
         assertNull(mGutsManager.mKeyToRemoveOnGutsClosed);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 56ed0e3..003d803 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -44,6 +44,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
@@ -66,6 +67,7 @@
     @Mock private ActivityStarterDelegate mActivityStarterDelegate;
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private ConfigurationController mConfigurationController;
+    @Mock private PeopleHubSectionFooterViewAdapter mPeopleHubAdapter;
 
     private NotificationSectionsManager mSectionsManager;
 
@@ -77,6 +79,7 @@
                         mActivityStarterDelegate,
                         mStatusBarStateController,
                         mConfigurationController,
+                        mPeopleHubAdapter,
                         2);
         // Required in order for the header inflation to work properly
         when(mNssl.generateLayoutParams(any(AttributeSet.class)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 4b82f59..012ebf72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -68,6 +68,7 @@
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.FooterView;
 import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
@@ -171,7 +172,8 @@
                 new FalsingManagerFake(),
                 mock(NotificationLockscreenUserManager.class),
                 mock(NotificationGutsManager.class),
-                new NotificationSectionsFeatureManager(new DeviceConfigProxyFake(), mContext));
+                new NotificationSectionsFeatureManager(new DeviceConfigProxyFake(), mContext),
+                mock(PeopleHubSectionFooterViewAdapter.class));
         mStackScroller = spy(mStackScrollerInternal);
         mStackScroller.setShelf(notificationShelf);
         mStackScroller.setStatusBar(mBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java
deleted file mode 100644
index 16f02d9..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoHideControllerTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.systemui.statusbar.phone;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.graphics.Rect;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.IWindowManager;
-import android.view.View;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/** atest AutoHideControllerTest */
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-@SmallTest
-public class AutoHideControllerTest extends SysuiTestCase {
-
-    private AutoHideController mAutoHideController;
-
-    private static final int FULL_MASK = 0xffffffff;
-
-    @Before
-    public void setUp() {
-        mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
-        mAutoHideController =
-                spy(new AutoHideController(mContext, Dependency.get(Dependency.MAIN_HANDLER),
-                        mock(NotificationRemoteInputManager.class), mock(IWindowManager.class)));
-        mAutoHideController.mDisplayId = DEFAULT_DISPLAY;
-        mAutoHideController.mSystemUiVisibility = View.VISIBLE;
-    }
-
-    @After
-    public void tearDown() {
-        mAutoHideController = null;
-    }
-
-    @Test
-    public void testSetSystemUiVisibilityEarlyReturnWithDifferentDisplay() {
-        mAutoHideController.setSystemUiVisibility(1, 1, 2, 3, 4, null, new Rect(), false);
-
-        verify(mAutoHideController, never()).notifySystemUiVisibilityChanged(anyInt());
-    }
-
-    @Test
-    public void testSetSystemUiVisibilityEarlyReturnWithSameVisibility() {
-        mAutoHideController
-                .setSystemUiVisibility(
-                        DEFAULT_DISPLAY, View.VISIBLE, 2, 3, 4, null, new Rect(), false);
-
-        verify(mAutoHideController, never()).notifySystemUiVisibilityChanged(anyInt());
-    }
-
-    // Test if status bar unhide status doesn't change without status bar.
-    @Test
-    public void testSetSystemUiVisibilityWithoutStatusBar() {
-        doReturn(false).when(mAutoHideController).hasStatusBar();
-        int expectedStatus = View.STATUS_BAR_UNHIDE;
-        mAutoHideController.mSystemUiVisibility =
-                View.SYSTEM_UI_FLAG_FULLSCREEN | View.STATUS_BAR_UNHIDE;
-
-        mAutoHideController.setSystemUiVisibility(
-                DEFAULT_DISPLAY, expectedStatus, 2, 3, FULL_MASK, null, new Rect(), false);
-
-        assertEquals("System UI visibility should not be changed",
-                expectedStatus, mAutoHideController.mSystemUiVisibility);
-        verify(mAutoHideController, times(1)).notifySystemUiVisibilityChanged(eq(expectedStatus));
-    }
-
-    @Test
-    public void testSetSystemUiVisibilityWithVisChanged() {
-        doReturn(true).when(mAutoHideController).hasStatusBar();
-        doReturn(true).when(mAutoHideController).hasNavigationBar();
-        mAutoHideController.mSystemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
-                | View.STATUS_BAR_UNHIDE
-                | View.NAVIGATION_BAR_UNHIDE;
-
-        mAutoHideController.setSystemUiVisibility(
-                DEFAULT_DISPLAY, View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE,
-                2, 3, FULL_MASK, null, new Rect(), false);
-
-        int expectedStatus = View.VISIBLE;
-        assertEquals(expectedStatus, mAutoHideController.mSystemUiVisibility);
-        verify(mAutoHideController).notifySystemUiVisibilityChanged(eq(expectedStatus));
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 72bea56..4a0b371 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -34,7 +34,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
+import android.testing.TestableResources;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -78,11 +80,14 @@
     private KeyguardBypassController mKeyguardBypassController;
     @Mock
     private DozeParameters mDozeParameters;
+    @Mock
+    private MetricsLogger mMetricsLogger;
     private BiometricUnlockController mBiometricUnlockController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        TestableResources res = getContext().getOrCreateTestableResources();
         when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
         when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
         when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
@@ -92,10 +97,11 @@
         mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
         mDependency.injectTestDependency(StatusBarWindowController.class,
                 mStatusBarWindowController);
+        res.addOverride(com.android.internal.R.integer.config_wakeUpDelayDoze, 0);
         mBiometricUnlockController = new BiometricUnlockController(mContext, mDozeScrimController,
                 mKeyguardViewMediator, mScrimController, mStatusBar, mKeyguardStateController,
-                mHandler, mUpdateMonitor, 0 /* wakeUpDelay */, mKeyguardBypassController,
-                mDozeParameters);
+                mHandler, mUpdateMonitor, res.getResources(), mKeyguardBypassController,
+                mDozeParameters, mMetricsLogger);
         mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
new file mode 100644
index 0000000..b05172c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.PowerManager;
+import android.testing.AndroidTestingRunner;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.doze.DozeEvent;
+import com.android.systemui.doze.DozeHost;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+import dagger.Lazy;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class DozeServiceHostTest extends SysuiTestCase {
+
+    private DozeServiceHost mDozeServiceHost;
+
+    @Mock private HeadsUpManagerPhone mHeadsUpManager;
+    @Mock private ScrimController mScrimController;
+    @Mock private DozeScrimController mDozeScrimController;
+    @Mock private Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
+    @Mock private VisualStabilityManager mVisualStabilityManager;
+    @Mock private KeyguardViewMediator mKeyguardViewMediator;
+    @Mock private StatusBarStateControllerImpl mStatusBarStateController;
+    @Mock private BatteryController mBatteryController;
+    @Mock private DeviceProvisionedController mDeviceProvisionedController;
+    @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock private AssistManager mAssistManager;
+    @Mock private DozeLog mDozeLog;
+    @Mock private PulseExpansionHandler mPulseExpansionHandler;
+    @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
+    @Mock private StatusBarWindowController mStatusBarWindowController;
+    @Mock private PowerManager mPowerManager;
+    @Mock private WakefulnessLifecycle mWakefullnessLifecycle;
+    @Mock private StatusBar mStatusBar;
+    @Mock private NotificationIconAreaController mNotificationIconAreaController;
+    @Mock private StatusBarWindowViewController mStatusBarWindowViewController;
+    @Mock private StatusBarWindowView mStatusBarWindow;
+    @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    @Mock private NotificationPanelView mNotificationPanel;
+    @Mock private View mAmbientIndicationContainer;
+    @Mock private BiometricUnlockController mBiometricUnlockController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController);
+        mDozeServiceHost = new DozeServiceHost(mDozeLog, mPowerManager, mWakefullnessLifecycle,
+                mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager,
+                mBatteryController, mScrimController, mBiometricUnlockControllerLazy,
+                mKeyguardViewMediator, mAssistManager, mDozeScrimController, mKeyguardUpdateMonitor,
+                mVisualStabilityManager, mPulseExpansionHandler, mStatusBarWindowController,
+                mNotificationWakeUpCoordinator);
+
+        mDozeServiceHost.initialize(mStatusBar, mNotificationIconAreaController,
+                mStatusBarWindowViewController, mStatusBarWindow, mStatusBarKeyguardViewManager,
+                mNotificationPanel, mAmbientIndicationContainer);
+    }
+
+    @Test
+    public void testStartStopDozing() {
+        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
+        when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+
+        assertFalse(mDozeServiceHost.getDozingRequested());
+
+        mDozeServiceHost.startDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(true));
+        verify(mStatusBar).updateIsKeyguard();
+
+        mDozeServiceHost.stopDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(false));
+    }
+
+
+    @Test
+    public void testPulseWhileDozing_updatesScrimController() {
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        mStatusBar.showKeyguardImpl();
+
+        // Keep track of callback to be able to stop the pulse
+//        DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1];
+//        doAnswer(invocation -> {
+//            pulseCallback[0] = invocation.getArgument(0);
+//            return null;
+//        }).when(mDozeScrimController).pulse(any(), anyInt());
+
+        // Starting a pulse should change the scrim controller to the pulsing state
+        mDozeServiceHost.pulseWhileDozing(new DozeHost.PulseCallback() {
+            @Override
+            public void onPulseStarted() {
+            }
+
+            @Override
+            public void onPulseFinished() {
+            }
+        }, DozeEvent.PULSE_REASON_NOTIFICATION);
+
+        ArgumentCaptor<DozeHost.PulseCallback> pulseCallbackArgumentCaptor =
+                ArgumentCaptor.forClass(DozeHost.PulseCallback.class);
+
+        verify(mDozeScrimController).pulse(
+                pulseCallbackArgumentCaptor.capture(), eq(DozeEvent.PULSE_REASON_NOTIFICATION));
+        verify(mStatusBar).updateScrimController();
+        reset(mStatusBar);
+
+        pulseCallbackArgumentCaptor.getValue().onPulseFinished();
+        assertFalse(mDozeScrimController.isPulsing());
+        verify(mStatusBar).updateScrimController();
+    }
+
+
+    @Test
+    public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() {
+        // Keep track of callback to be able to stop the pulse
+        final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1];
+        doAnswer(invocation -> {
+            pulseCallback[0] = invocation.getArgument(0);
+            return null;
+        }).when(mDozeScrimController).pulse(any(), anyInt());
+
+        // Starting a pulse while docking should suppress wakeup gesture
+        mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class),
+                DozeEvent.PULSE_REASON_DOCKING);
+        verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(true));
+
+        // Ending a pulse should restore wakeup gesture
+        pulseCallback[0].onPulseFinished();
+        verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(false));
+    }
+
+    @Test
+    public void testPulseWhileDozing_notifyAuthInterrupt() {
+        HashSet<Integer> reasonsWantingAuth = new HashSet<>(
+                Collections.singletonList(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN));
+        HashSet<Integer> reasonsSkippingAuth = new HashSet<>(
+                Arrays.asList(DozeEvent.PULSE_REASON_INTENT,
+                        DozeEvent.PULSE_REASON_NOTIFICATION,
+                        DozeEvent.PULSE_REASON_SENSOR_SIGMOTION,
+                        DozeEvent.REASON_SENSOR_PICKUP,
+                        DozeEvent.REASON_SENSOR_DOUBLE_TAP,
+                        DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS,
+                        DozeEvent.PULSE_REASON_DOCKING,
+                        DozeEvent.REASON_SENSOR_WAKE_UP,
+                        DozeEvent.REASON_SENSOR_TAP));
+        HashSet<Integer> reasonsThatDontPulse = new HashSet<>(
+                Arrays.asList(DozeEvent.REASON_SENSOR_PICKUP,
+                        DozeEvent.REASON_SENSOR_DOUBLE_TAP,
+                        DozeEvent.REASON_SENSOR_TAP));
+
+        doAnswer(invocation -> {
+            DozeHost.PulseCallback callback = invocation.getArgument(0);
+            callback.onPulseStarted();
+            return null;
+        }).when(mDozeScrimController).pulse(any(), anyInt());
+
+        mDozeServiceHost.mWakeLockScreenPerformsAuth = true;
+        for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) {
+            reset(mKeyguardUpdateMonitor);
+            mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), i);
+            if (reasonsWantingAuth.contains(i)) {
+                verify(mKeyguardUpdateMonitor).onAuthInterruptDetected(eq(true));
+            } else if (reasonsSkippingAuth.contains(i) || reasonsThatDontPulse.contains(i)) {
+                verify(mKeyguardUpdateMonitor, never()).onAuthInterruptDetected(eq(true));
+            } else {
+                throw new AssertionError("Reason " + i + " isn't specified as wanting or skipping"
+                        + " passive auth. Please consider how this pulse reason should behave.");
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 6fcf550..2068f7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -102,27 +102,27 @@
 
         mHeadsUpManager.snooze();
 
-        assertTrue(mHeadsUpManager.isSnoozed(mEntry.notification.getPackageName()));
+        assertTrue(mHeadsUpManager.isSnoozed(mEntry.getSbn().getPackageName()));
     }
 
     @Test
     public void testSwipedOutNotification() {
         mHeadsUpManager.showNotification(mEntry);
-        mHeadsUpManager.addSwipedOutNotification(mEntry.key);
+        mHeadsUpManager.addSwipedOutNotification(mEntry.getKey());
 
         // Remove should succeed because the notification is swiped out
-        mHeadsUpManager.removeNotification(mEntry.key, false /* releaseImmediately */);
+        mHeadsUpManager.removeNotification(mEntry.getKey(), false /* releaseImmediately */);
 
-        assertFalse(mHeadsUpManager.isAlerting(mEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(mEntry.getKey()));
     }
 
     @Test
     public void testCanRemoveImmediately_swipedOut() {
         mHeadsUpManager.showNotification(mEntry);
-        mHeadsUpManager.addSwipedOutNotification(mEntry.key);
+        mHeadsUpManager.addSwipedOutNotification(mEntry.getKey());
 
         // Notification is swiped so it can be immediately removed.
-        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.key));
+        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.getKey()));
     }
 
     @Test
@@ -135,7 +135,7 @@
         mHeadsUpManager.showNotification(laterEntry);
 
         // Notification is "behind" a higher priority notification so we can remove it immediately.
-        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.key));
+        assertTrue(mHeadsUpManager.canRemoveImmediately(mEntry.getKey()));
     }
 
 
@@ -143,7 +143,7 @@
     public void testExtendHeadsUp() {
         mHeadsUpManager.showNotification(mEntry);
         Runnable pastNormalTimeRunnable =
-                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.key);
+                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.getKey());
         mTestHandler.postDelayed(pastNormalTimeRunnable,
                 TEST_AUTO_DISMISS_TIME + mHeadsUpManager.mExtensionTime / 2);
         mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_TIMEOUT_TIME);
@@ -155,6 +155,6 @@
 
         assertFalse("Test timed out", mTimedOut);
         assertTrue("Pulse was not extended", mLivesPastNormalTime);
-        assertFalse(mHeadsUpManager.isAlerting(mEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(mEntry.getKey()));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
new file mode 100644
index 0000000..6260d53
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.view.AppearanceRegion;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class LightBarControllerTest extends SysuiTestCase {
+
+    private LightBarTransitionsController mLightBarTransitionsController;
+    private SysuiDarkIconDispatcher mStatusBarIconController;
+    private LightBarController mLightBarController;
+
+    @Before
+    public void setup() {
+        mStatusBarIconController = mock(SysuiDarkIconDispatcher.class);
+        mLightBarTransitionsController = mock(LightBarTransitionsController.class);
+        when(mStatusBarIconController.getTransitionsController()).thenReturn(
+                mLightBarTransitionsController);
+        mLightBarController = new LightBarController(mContext, mStatusBarIconController,
+                mock(BatteryController.class));
+    }
+
+    @Test
+    public void testOnStatusBarAppearanceChanged_multipleStacks_allStacksLight() {
+        final Rect firstBounds = new Rect(0, 0, 1, 1);
+        final Rect secondBounds = new Rect(1, 0, 2, 1);
+        final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+                new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, firstBounds),
+                new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, secondBounds)
+        };
+        mLightBarController.onStatusBarAppearanceChanged(
+                appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+                false /* navbarColorManagedByIme */);
+        verify(mStatusBarIconController).setIconsDarkArea(eq(null));
+        verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+    }
+
+    @Test
+    public void testOnStatusBarAppearanceChanged_multipleStacks_oneStackLightOneStackDark() {
+        final Rect firstBounds = new Rect(0, 0, 1, 1);
+        final Rect secondBounds = new Rect(1, 0, 2, 1);
+        final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+                new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, firstBounds),
+                new AppearanceRegion(0 /* appearance */, secondBounds)
+        };
+        mLightBarController.onStatusBarAppearanceChanged(
+                appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+                false /* navbarColorManagedByIme */);
+        verify(mStatusBarIconController).setIconsDarkArea(eq(firstBounds));
+        verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+    }
+
+    @Test
+    public void testOnStatusBarAppearanceChanged_multipleStacks_oneStackDarkOneStackLight() {
+        final Rect firstBounds = new Rect(0, 0, 1, 1);
+        final Rect secondBounds = new Rect(1, 0, 2, 1);
+        final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+                new AppearanceRegion(0 /* appearance */, firstBounds),
+                new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, secondBounds)
+        };
+        mLightBarController.onStatusBarAppearanceChanged(
+                appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+                false /* navbarColorManagedByIme */);
+        verify(mStatusBarIconController).setIconsDarkArea(eq(secondBounds));
+        verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+    }
+
+    @Test
+    public void testOnStatusBarAppearanceChanged_multipleStacks_allStacksDark() {
+        final Rect firstBounds = new Rect(0, 0, 1, 1);
+        final Rect secondBounds = new Rect(1, 0, 2, 1);
+        final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+                new AppearanceRegion(0 /* appearance */, firstBounds),
+                new AppearanceRegion(0 /* appearance */, secondBounds)
+        };
+        mLightBarController.onStatusBarAppearanceChanged(
+                appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+                false /* navbarColorManagedByIme */);
+        verify(mLightBarTransitionsController).setIconsDark(eq(false), anyBoolean());
+    }
+
+    @Test
+    public void testOnStatusBarAppearanceChanged_singleStack_light() {
+        final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+                new AppearanceRegion(APPEARANCE_LIGHT_TOP_BAR, new Rect(0, 0, 1, 1))
+        };
+        mLightBarController.onStatusBarAppearanceChanged(
+                appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+                false /* navbarColorManagedByIme */);
+        verify(mStatusBarIconController).setIconsDarkArea(eq(null));
+        verify(mLightBarTransitionsController).setIconsDark(eq(true), anyBoolean());
+    }
+
+    @Test
+    public void testOnStatusBarAppearanceChanged_singleStack_dark() {
+        final AppearanceRegion[] appearanceRegions = new AppearanceRegion[]{
+                new AppearanceRegion(0, new Rect(0, 0, 1, 1))
+        };
+        mLightBarController.onStatusBarAppearanceChanged(
+                appearanceRegions, true /* sbModeChanged */, MODE_TRANSPARENT,
+                false /* navbarColorManagedByIme */);
+        verify(mLightBarTransitionsController).setIconsDark(eq(false), anyBoolean());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
index 2254234..5b54fba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java
@@ -102,8 +102,8 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // A suppressed summary should transfer its alert state to the child.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertTrue(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertTrue(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -120,14 +120,14 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Add second child notification so that summary is no longer suppressed.
-        mPendingEntries.put(childEntry2.key, childEntry2);
+        mPendingEntries.put(childEntry2.getKey(), childEntry2);
         mNotificationEntryListener.onPendingEntryAdded(childEntry2);
         mGroupManager.onEntryAdded(childEntry2);
 
         // The alert state should transfer back to the summary as there is now more than one
         // child and the summary should no longer be suppressed.
-        assertTrue(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertFalse(mHeadsUpManager.isAlerting(childEntry.key));
+        assertTrue(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -147,12 +147,12 @@
         mGroupAlertTransferHelper.onDozingChanged(true);
 
         // Add second child notification so that summary is no longer suppressed.
-        mPendingEntries.put(childEntry2.key, childEntry2);
+        mPendingEntries.put(childEntry2.getKey(), childEntry2);
         mNotificationEntryListener.onPendingEntryAdded(childEntry2);
         mGroupManager.onEntryAdded(childEntry2);
 
         // Dozing changed so no reason to re-alert summary.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
     }
 
     @Test
@@ -168,8 +168,8 @@
 
         // Alert is immediately removed from summary, but we do not show child yet either as its
         // content is not inflated.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertFalse(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
         assertTrue(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
     }
 
@@ -189,8 +189,8 @@
         mNotificationEntryListener.onEntryReinflated(childEntry);
 
         // Alert is immediately removed from summary, and we show child as its content is inflated.
-        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.key));
-        assertTrue(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(summaryEntry.getKey()));
+        assertTrue(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -209,7 +209,7 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Add second child notification so that summary is no longer suppressed.
-        mPendingEntries.put(childEntry2.key, childEntry2);
+        mPendingEntries.put(childEntry2.getKey(), childEntry2);
         mNotificationEntryListener.onPendingEntryAdded(childEntry2);
         mGroupManager.onEntryAdded(childEntry2);
 
@@ -220,7 +220,7 @@
 
         verify(childEntry.getRow(), times(1)).freeContentViewWhenSafe(mHeadsUpManager
             .getContentFlag());
-        assertFalse(mHeadsUpManager.isAlerting(childEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(childEntry.getKey()));
     }
 
     @Test
@@ -255,10 +255,10 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Notify that entry changed groups.
-        StatusBarNotification oldNotification = childEntry.notification;
-        StatusBarNotification newSbn = spy(childEntry.notification.clone());
+        StatusBarNotification oldNotification = childEntry.getSbn();
+        StatusBarNotification newSbn = spy(childEntry.getSbn().clone());
         doReturn("other_group").when(newSbn).getGroupKey();
-        childEntry.setNotification(newSbn);
+        childEntry.setSbn(newSbn);
         mGroupManager.onEntryUpdated(childEntry, oldNotification);
 
         assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
@@ -278,10 +278,10 @@
         mGroupManager.onEntryAdded(childEntry);
 
         // Update that child to a summary.
-        StatusBarNotification oldNotification = childEntry.notification;
-        childEntry.setNotification(
+        StatusBarNotification oldNotification = childEntry.getSbn();
+        childEntry.setSbn(
                 mGroupTestHelper.createSummaryNotification(
-                        Notification.GROUP_ALERT_SUMMARY, 47).notification);
+                        Notification.GROUP_ALERT_SUMMARY, 47).getSbn());
         mGroupManager.onEntryUpdated(childEntry, oldNotification);
 
         assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
index 493b74d..19ce1ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java
@@ -75,7 +75,7 @@
         mGroupManager.onEntryAdded(summaryEntry);
         mGroupManager.onEntryAdded(childEntry);
 
-        assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.notification));
+        assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.getSbn()));
     }
 
     @Test
@@ -87,7 +87,7 @@
         mGroupManager.onEntryAdded(childEntry);
         mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
 
-        assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.notification));
+        assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
     }
 
     @Test
@@ -99,8 +99,8 @@
         mGroupManager.onEntryAdded(childEntry);
         mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
 
-        assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.notification));
-        assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry.notification));
+        assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
+        assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
     }
 
     @Test
@@ -113,7 +113,7 @@
 
         mGroupManager.onEntryRemoved(childEntry);
 
-        assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.notification));
+        assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn()));
     }
 
     @Test
@@ -126,8 +126,8 @@
 
         mGroupManager.onEntryRemoved(summaryEntry);
 
-        assertNull(mGroupManager.getGroupSummary(childEntry.notification));
-        assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.notification));
+        assertNull(mGroupManager.getGroupSummary(childEntry.getSbn()));
+        assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn()));
     }
 
     @Test
@@ -137,13 +137,13 @@
         mGroupManager.onEntryAdded(summaryEntry);
         mGroupManager.onEntryAdded(childEntry);
         mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification());
-        when(mHeadsUpManager.isAlerting(childEntry.key)).thenReturn(true);
+        when(mHeadsUpManager.isAlerting(childEntry.getKey())).thenReturn(true);
 
         mGroupManager.onHeadsUpStateChanged(childEntry, true);
 
         // Child entries that are heads upped should be considered separate groups visually even if
         // they are the same group logically
-        assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry.notification));
-        assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry.notification));
+        assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry.getSbn()));
+        assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry.getSbn()));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
index f1a7905..a49ae35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupTestHelper.java
@@ -87,7 +87,7 @@
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
         entry.setRow(row);
         when(row.getEntry()).thenReturn(entry);
-        when(row.getStatusBarNotification()).thenReturn(entry.sbn());
+        when(row.getStatusBarNotification()).thenReturn(entry.getSbn());
         when(row.isInflationFlagSet(anyInt())).thenReturn(true);
         return entry;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index cff6635..4853f20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -57,6 +57,7 @@
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -236,8 +237,11 @@
                     mock(PluginManager.class),
                     mock(ShadeController.class),
                     mock(NotificationLockscreenUserManager.class),
-                    new NotificationEntryManager(new NotificationData(mock(
-                            NotificationSectionsFeatureManager.class), mock(NotifLog.class)),
+                    new NotificationEntryManager(
+                            new NotificationData(
+                                    mock(NotificationSectionsFeatureManager.class),
+                                    mock(NotifLog.class),
+                                    mock(PeopleNotificationIdentifier.class)),
                             mock(NotifLog.class)),
                     mock(KeyguardStateController.class),
                     statusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index f3ff7ec..85c247e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -21,9 +21,11 @@
 import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -33,8 +35,8 @@
 import static org.mockito.Mockito.when;
 
 import android.animation.Animator;
-import android.animation.ValueAnimator;
 import android.app.AlarmManager;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Handler;
 import android.testing.AndroidTestingRunner;
@@ -44,13 +46,13 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
-import com.android.internal.util.function.TriConsumer;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.wakelock.WakeLock;
+import com.android.systemui.util.wakelock.DelayedWakeLock;
 import com.android.systemui.utils.os.FakeHandler;
 
 import org.junit.After;
@@ -58,17 +60,20 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.function.Consumer;
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 @SmallTest
 public class ScrimControllerTest extends SysuiTestCase {
 
-    private SynchronousScrimController mScrimController;
+    private ScrimController mScrimController;
     private ScrimView mScrimBehind;
     private ScrimView mScrimInFront;
     private ScrimView mScrimForBubble;
@@ -76,52 +81,159 @@
     private float mScrimBehindAlpha;
     private GradientColors mScrimInFrontColor;
     private int mScrimVisibility;
-    private DozeParameters mDozeParamenters;
-    private WakeLock mWakeLock;
     private boolean mAlwaysOnEnabled;
-    private AlarmManager mAlarmManager;
     private TestableLooper mLooper;
+    @Mock
+    private AlarmManager mAlarmManager;
+    @Mock
+    private DozeParameters mDozeParamenters;
+    @Mock
+    LightBarController mLightBarController;
+    @Mock
+    Resources mResources;
+    @Mock
+    DelayedWakeLock.Builder mDelayedWakeLockBuilder;
+    @Mock
+    private DelayedWakeLock mWakeLock;
+    @Mock
+    KeyguardStateController mKeyguardStateController;
+    @Mock
+    KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock
+    private SysuiColorExtractor mSysuiColorExtractor;
 
 
+    private static class AnimatorListener implements Animator.AnimatorListener {
+        private int mNumStarts;
+        private int mNumEnds;
+        private int mNumCancels;
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            mNumStarts++;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mNumEnds++;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mNumCancels++;
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+
+        }
+
+        public int getNumStarts() {
+            return mNumStarts;
+        }
+
+        public int getNumEnds() {
+            return mNumEnds;
+        }
+
+        public int getNumCancels() {
+            return mNumCancels;
+        }
+
+        public void reset() {
+            mNumStarts = 0;
+            mNumEnds = 0;
+            mNumCancels = 0;
+        }
+    };
+
+    private AnimatorListener mAnimatorListener = new AnimatorListener();
+
+
+    private void finishAnimationsImmediately() {
+        // Execute code that will trigger animations.
+        mScrimController.onPreDraw();
+        // Force finish all animations.
+        mLooper.processAllMessages();
+        endAnimation(mScrimBehind);
+        endAnimation(mScrimInFront);
+        endAnimation(mScrimForBubble);
+
+        Assert.assertEquals("Animators did not finish",
+                mAnimatorListener.getNumStarts(), mAnimatorListener.getNumEnds());
+    }
+
+    private void endAnimation(View scrimView) {
+        Animator animator = getAnimator(scrimView);
+        if (animator != null) {
+            animator.end();
+        }
+    }
+
+    private Animator getAnimator(View scrimView) {
+        return (Animator) scrimView.getTag(ScrimController.TAG_KEY_ANIM);
+    }
+
     @Before
     public void setup() {
+        MockitoAnnotations.initMocks(this);
+
         mScrimBehind = spy(new ScrimView(getContext()));
         mScrimInFront = new ScrimView(getContext());
         mScrimForBubble = new ScrimView(getContext());
-        mWakeLock = mock(WakeLock.class);
-        mAlarmManager = mock(AlarmManager.class);
         mAlwaysOnEnabled = true;
-        mDozeParamenters = mock(DozeParameters.class);
         mLooper = TestableLooper.get(this);
-        mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
+        DejankUtils.setImmediate(true);
+
+        // ScrimController uses mScrimBehind to delay some callbacks that we should run immediately.
+        doAnswer(invocation -> {
+            ((Runnable) invocation.getArgument(0)).run();
+            return null;
+        }).when(mScrimBehind).postOnAnimationDelayed(any(Runnable.class), anyLong());
+
         when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
         when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
-        DejankUtils.setImmediate(true);
-        mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
-                mScrimForBubble,
-                (scrimState, scrimBehindAlpha, scrimInFrontColor) -> {
-                    mScrimState = scrimState;
-                    mScrimBehindAlpha = scrimBehindAlpha;
-                    mScrimInFrontColor = scrimInFrontColor;
-                },
-                visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager,
-                mock(KeyguardStateController.class));
+
+        doAnswer((Answer<Void>) invocation -> {
+            mScrimState = invocation.getArgument(0);
+            mScrimBehindAlpha = invocation.getArgument(1);
+            mScrimInFrontColor = invocation.getArgument(2);
+            return null;
+        }).when(mLightBarController).setScrimState(
+                any(ScrimState.class), anyFloat(), any(GradientColors.class));
+
+        when(mDelayedWakeLockBuilder.setHandler(any(Handler.class)))
+                .thenReturn(mDelayedWakeLockBuilder);
+        when(mDelayedWakeLockBuilder.setTag(any(String.class)))
+                .thenReturn(mDelayedWakeLockBuilder);
+        when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock);
+
+        when(mSysuiColorExtractor.getNeutralColors()).thenReturn(new GradientColors());
+
+        mScrimController = new ScrimController(mLightBarController,
+                mDozeParamenters, mAlarmManager, mKeyguardStateController,
+                mResources, mDelayedWakeLockBuilder,
+                new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor, mSysuiColorExtractor);
+        mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
+        mScrimController.attachViews(mScrimBehind, mScrimInFront, mScrimForBubble);
+        mScrimController.setAnimatorListener(mAnimatorListener);
+
         mScrimController.setHasBackdrop(false);
         mScrimController.setWallpaperSupportsAmbientMode(false);
         mScrimController.transitionTo(ScrimState.KEYGUARD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
     }
 
     @After
     public void tearDown() {
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         DejankUtils.setImmediate(false);
     }
 
     @Test
     public void transitionToKeyguard() {
         mScrimController.transitionTo(ScrimState.KEYGUARD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(TRANSPARENT /* front */,
                 SEMI_TRANSPARENT /* back */,
@@ -135,10 +247,10 @@
     @Test
     public void transitionToOff() {
         mScrimController.transitionTo(ScrimState.OFF);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(OPAQUE /* front */,
-                SEMI_TRANSPARENT /* back */,
+                OPAQUE /* back */,
                 TRANSPARENT /* bubble */);
 
         assertScrimTint(true /* front */,
@@ -149,7 +261,7 @@
     @Test
     public void transitionToAod_withRegularWallpaper() {
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(TRANSPARENT /* front */,
                 OPAQUE /* back */,
@@ -164,7 +276,7 @@
     public void transitionToAod_withAodWallpaper() {
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(TRANSPARENT /* front */,
                 TRANSPARENT /* back */,
@@ -172,7 +284,7 @@
 
         // Pulsing notification should conserve AOD wallpaper.
         mScrimController.transitionTo(ScrimState.PULSING);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(TRANSPARENT /* front */,
                 TRANSPARENT /* back */,
@@ -184,7 +296,7 @@
         mScrimController.setHasBackdrop(true);
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(TRANSPARENT /* front */,
                 OPAQUE /* back */,
@@ -199,9 +311,9 @@
     public void setHasBackdrop_withAodWallpaperAndAlbumArt() {
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         mScrimController.setHasBackdrop(true);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(TRANSPARENT /* front */,
                 OPAQUE /* back */,
@@ -217,7 +329,7 @@
         // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
         mScrimController.transitionTo(ScrimState.KEYGUARD);
         mScrimController.setAodFrontScrimAlpha(0.5f);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimAlpha(TRANSPARENT /* front */,
                 SEMI_TRANSPARENT /* back */,
@@ -225,7 +337,7 @@
 
         // ... but that it does take effect once we enter the AOD state.
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(SEMI_TRANSPARENT /* front */,
                 OPAQUE /* back */,
                 TRANSPARENT /* bubble */);
@@ -240,7 +352,7 @@
         // for a bit.
         mScrimController.transitionTo(ScrimState.UNLOCKED);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(OPAQUE /* front */,
                 OPAQUE /* back */,
                 TRANSPARENT /* bubble */);
@@ -250,7 +362,7 @@
         mAlwaysOnEnabled = false;
         mScrimController.transitionTo(ScrimState.UNLOCKED);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         mScrimController.setAodFrontScrimAlpha(0.3f);
         Assert.assertEquals(ScrimState.AOD.getFrontAlpha(), mScrimInFront.getViewAlpha(), 0.001f);
         Assert.assertNotEquals(0.3f, mScrimInFront.getViewAlpha(), 0.001f);
@@ -266,13 +378,13 @@
         // the back scrim opacity - otherwise it would hide AoD wallpapers.
         mScrimController.setWallpaperSupportsAmbientMode(false);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(TRANSPARENT /* front */,
                 OPAQUE /* back */,
                 TRANSPARENT /* bubble */);
 
         mScrimController.transitionTo(ScrimState.PULSING);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         // Front scrim should be transparent, but tinted
         // Back scrim should be semi-transparent so the user can see the wallpaper
         // Pulse callback should have been invoked
@@ -286,14 +398,14 @@
 
         // ... and when ambient goes dark, front scrim should be semi-transparent
         mScrimController.setAodFrontScrimAlpha(0.5f);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         // Front scrim should be semi-transparent
         assertScrimAlpha(SEMI_TRANSPARENT /* front */,
                 OPAQUE /* back */,
                 TRANSPARENT /* bubble */);
 
         mScrimController.setWakeLockScreenSensorActive(true);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(SEMI_TRANSPARENT /* front */,
                 SEMI_TRANSPARENT /* back */,
                 TRANSPARENT /* bubble */);
@@ -305,7 +417,7 @@
     @Test
     public void transitionToKeyguardBouncer() {
         mScrimController.transitionTo(ScrimState.BOUNCER);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         // Front scrim should be transparent
         // Back scrim should be visible without tint
         assertScrimAlpha(TRANSPARENT /* front */,
@@ -320,7 +432,7 @@
     @Test
     public void transitionToBouncer() {
         mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         // Front scrim should be transparent
         // Back scrim should be visible without tint
         assertScrimAlpha(SEMI_TRANSPARENT /* front */,
@@ -335,7 +447,7 @@
     public void transitionToUnlocked() {
         mScrimController.setPanelExpansion(0f);
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(TRANSPARENT /* front */,
                 TRANSPARENT /* back */,
                 TRANSPARENT /* bubble */);
@@ -354,7 +466,7 @@
     @Test
     public void transitionToBubbleExpanded() {
         mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         assertScrimTint(false /* front */,
                 false /* behind */,
@@ -374,15 +486,15 @@
     @Test
     public void scrimStateCallback() {
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         Assert.assertEquals(mScrimState, ScrimState.UNLOCKED);
 
         mScrimController.transitionTo(ScrimState.BOUNCER);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         Assert.assertEquals(mScrimState, ScrimState.BOUNCER);
 
         mScrimController.transitionTo(ScrimState.BOUNCER_SCRIMMED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
     }
 
@@ -391,18 +503,18 @@
         mScrimController.setPanelExpansion(0f);
         mScrimController.setPanelExpansion(0.5f);
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         reset(mScrimBehind);
         mScrimController.setPanelExpansion(0f);
         mScrimController.setPanelExpansion(1.0f);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
                 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
 
         mScrimController.setPanelExpansion(0f);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         Assert.assertEquals("Scrim alpha should change after setPanelExpansion",
                 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
@@ -413,7 +525,7 @@
         mScrimController.setPanelExpansion(0f);
         mScrimController.setPanelExpansion(0.5f);
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         final float scrimAlpha = mScrimBehind.getViewAlpha();
         reset(mScrimBehind);
@@ -425,7 +537,7 @@
 
         mScrimController.setExpansionAffectsAlpha(true);
         mScrimController.setPanelExpansion(0.1f);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         Assert.assertNotEquals("Scrim opacity should change when setExpansionAffectsAlpha "
                 + "is true", scrimAlpha, mScrimBehind.getViewAlpha(), 0.01f);
     }
@@ -435,7 +547,7 @@
         // Simulate unlock with fingerprint
         mScrimController.transitionTo(ScrimState.AOD);
         mScrimController.setPanelExpansion(0f);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         mScrimController.transitionTo(ScrimState.UNLOCKED);
 
         // Immediately tinted black after the transition starts
@@ -443,7 +555,7 @@
                 true /* behind */,
                 true  /* bubble */);
 
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         // All scrims should be transparent at the end of fade transition.
         assertScrimAlpha(TRANSPARENT /* front */,
@@ -460,7 +572,7 @@
     public void scrimBlanksBeforeLeavingAod() {
         // Simulate unlock with fingerprint
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         mScrimController.transitionTo(ScrimState.UNLOCKED,
                 new ScrimController.Callback() {
                     @Override
@@ -475,7 +587,7 @@
                                 mScrimVisibility, OPAQUE);
                     }
                 });
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
     }
 
     @Test
@@ -483,7 +595,7 @@
         boolean[] blanked = {false};
         // Simulate unlock with fingerprint
         mScrimController.transitionTo(ScrimState.PULSING);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         mScrimController.transitionTo(ScrimState.UNLOCKED,
                 new ScrimController.Callback() {
                     @Override
@@ -491,7 +603,7 @@
                         blanked[0] = true;
                     }
                 });
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
     }
 
@@ -515,7 +627,7 @@
                 callOrder[2] = ++currentCall[0];
             }
         });
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         Assert.assertEquals("onStart called in wrong order", 1, callOrder[0]);
         Assert.assertEquals("onDisplayBlanked called in wrong order", 2, callOrder[1]);
         Assert.assertEquals("onFinished called in wrong order", 3, callOrder[2]);
@@ -545,21 +657,21 @@
         mScrimController.transitionTo(ScrimState.AOD);
         verify(mWakeLock).acquire(anyString());
         verify(mWakeLock, never()).release(anyString());
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         verify(mWakeLock).release(anyString());
     }
 
     @Test
     public void testDoesNotHoldWakeLock_whenUnlocking() {
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         verifyZeroInteractions(mWakeLock);
     }
 
     @Test
     public void testCallbackInvokedOnSameStateTransition() {
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         ScrimController.Callback callback = mock(ScrimController.Callback.class);
         mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
         verify(callback).onFinished();
@@ -569,13 +681,13 @@
     public void testHoldsAodWallpaperAnimationLock() {
         // Pre-conditions
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         reset(mWakeLock);
 
         mScrimController.onHideWallpaperTimeout();
         verify(mWakeLock).acquire(anyString());
         verify(mWakeLock, never()).release(anyString());
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         verify(mWakeLock).release(anyString());
     }
 
@@ -583,13 +695,13 @@
     public void testHoldsPulsingWallpaperAnimationLock() {
         // Pre-conditions
         mScrimController.transitionTo(ScrimState.PULSING);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         reset(mWakeLock);
 
         mScrimController.onHideWallpaperTimeout();
         verify(mWakeLock).acquire(anyString());
         verify(mWakeLock, never()).release(anyString());
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         verify(mWakeLock).release(anyString());
     }
 
@@ -638,29 +750,29 @@
     public void testConservesExpansionOpacityAfterTransition() {
         mScrimController.transitionTo(ScrimState.UNLOCKED);
         mScrimController.setPanelExpansion(0.5f);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         final float expandedAlpha = mScrimBehind.getViewAlpha();
 
         mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         mScrimController.transitionTo(ScrimState.UNLOCKED);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
 
         Assert.assertEquals("Scrim expansion opacity wasn't conserved when transitioning back",
                 expandedAlpha, mScrimBehind.getViewAlpha(), 0.01f);
     }
 
     @Test
-    public void cancelsOldAnimationBeforeBlanking() {
+    public void testCancelsOldAnimationBeforeBlanking() {
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         // Consume whatever value we had before
-        mScrimController.wasAnimationJustCancelled();
+        mAnimatorListener.reset();
 
         mScrimController.transitionTo(ScrimState.KEYGUARD);
-        mScrimController.finishAnimationsImmediately();
-        Assert.assertTrue(mScrimController.wasAnimationJustCancelled());
+        finishAnimationsImmediately();
+        Assert.assertTrue("Animators not canceled", mAnimatorListener.getNumCancels() != 0);
     }
 
     @Test
@@ -679,13 +791,13 @@
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.setKeyguardOccluded(true);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(TRANSPARENT /* front */,
                 OPAQUE /* behind */,
                 TRANSPARENT /* bubble */);
 
         mScrimController.transitionTo(ScrimState.PULSING);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(TRANSPARENT /* front */,
                 OPAQUE /* behind */,
                 TRANSPARENT /* bubble */);
@@ -695,13 +807,13 @@
     public void testHidesShowWhenLockedActivity_whenAlreadyInAod() {
         mScrimController.setWallpaperSupportsAmbientMode(true);
         mScrimController.transitionTo(ScrimState.AOD);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(TRANSPARENT /* front */,
                 TRANSPARENT /* behind */,
                 TRANSPARENT /* bubble */);
 
         mScrimController.setKeyguardOccluded(true);
-        mScrimController.finishAnimationsImmediately();
+        finishAnimationsImmediately();
         assertScrimAlpha(TRANSPARENT /* front */,
                 OPAQUE /* behind */,
                 TRANSPARENT /* bubble */);
@@ -716,7 +828,7 @@
                 continue;
             }
             mScrimController.transitionTo(state);
-            mScrimController.finishAnimationsImmediately();
+            finishAnimationsImmediately();
             Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
                     mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
                     mScrimBehind.isClickable());
@@ -747,6 +859,22 @@
                 mScrimForBubble.getDefaultFocusHighlightEnabled());
     }
 
+    @Test
+    public void testIsLowPowerMode() {
+        HashSet<ScrimState> lowPowerModeStates = new HashSet<>(Arrays.asList(
+                ScrimState.OFF, ScrimState.AOD, ScrimState.PULSING));
+        HashSet<ScrimState> regularStates = new HashSet<>(Arrays.asList(
+                ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, ScrimState.BOUNCER,
+                ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, ScrimState.UNLOCKED,
+                ScrimState.BUBBLE_EXPANDED));
+
+        for (ScrimState state : ScrimState.values()) {
+            if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) {
+                Assert.fail("Scrim state not whitelisted nor blacklisted as low power mode");
+            }
+        }
+    }
+
     private void assertScrimTint(boolean front, boolean behind, boolean bubble) {
         Assert.assertEquals("Tint test failed at state " + mScrimController.getState()
                         + " with scrim: " + getScrimName(mScrimInFront) + " and tint: "
@@ -806,83 +934,4 @@
                 visibility /* expected */,
                 mScrimVisibility);
     }
-
-    /**
-     * Special version of ScrimController where animations have 0 duration for test purposes.
-     */
-    private class SynchronousScrimController extends ScrimController {
-
-        private boolean mAnimationCancelled;
-        boolean mOnPreDrawCalled;
-
-        SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
-                ScrimView scrimForBubble,
-                TriConsumer<ScrimState, Float, GradientColors> scrimStateListener,
-                Consumer<Integer> scrimVisibleListener, DozeParameters dozeParameters,
-                AlarmManager alarmManager, KeyguardStateController keyguardStateController) {
-            super(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener,
-                    scrimVisibleListener, dozeParameters, alarmManager, keyguardStateController);
-        }
-
-        @Override
-        public boolean onPreDraw() {
-            mOnPreDrawCalled = true;
-            return super.onPreDraw();
-        }
-
-        void finishAnimationsImmediately() {
-            boolean[] animationFinished = {false};
-            setOnAnimationFinished(() -> animationFinished[0] = true);
-            // Execute code that will trigger animations.
-            onPreDraw();
-            // Force finish all animations.
-            mLooper.processAllMessages();
-            endAnimation(mScrimBehind, TAG_KEY_ANIM);
-            endAnimation(mScrimInFront, TAG_KEY_ANIM);
-            endAnimation(mScrimForBubble, TAG_KEY_ANIM);
-
-            if (!animationFinished[0]) {
-                throw new IllegalStateException("Animation never finished");
-            }
-        }
-
-        boolean wasAnimationJustCancelled() {
-            final boolean wasCancelled = mAnimationCancelled;
-            mAnimationCancelled = false;
-            return wasCancelled;
-        }
-
-        private void endAnimation(View scrimView, int tag) {
-            Animator animator = (Animator) scrimView.getTag(tag);
-            if (animator != null) {
-                animator.end();
-            }
-        }
-
-        @Override
-        protected void cancelAnimator(ValueAnimator previousAnimator) {
-            super.cancelAnimator(previousAnimator);
-            mAnimationCancelled = true;
-        }
-
-        @Override
-        protected Handler getHandler() {
-            return new FakeHandler(mLooper.getLooper());
-        }
-
-        @Override
-        protected WakeLock createWakeLock() {
-            return mWakeLock;
-        }
-
-        /**
-         * Do not wait for a frame since we're in a test environment.
-         *
-         * @param callback What to execute.
-         */
-        @Override
-        protected void doOnTheNextFrame(Runnable callback) {
-            callback.run();
-        }
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 210c9d6..c0c42ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -132,7 +132,7 @@
         TestableLooper.get(this).processAllMessages();
 
         assertFalse("The panel shouldn't allow heads up while disabled",
-                mStatusBar.canHeadsUp(entry, entry.sbn()));
+                mStatusBar.canHeadsUp(entry, entry.getSbn()));
     }
 
     @Test
@@ -149,7 +149,7 @@
         TestableLooper.get(this).processAllMessages();
 
         assertFalse("The panel shouldn't allow heads up while notitifcation shade disabled",
-                mStatusBar.canHeadsUp(entry, entry.sbn()));
+                mStatusBar.canHeadsUp(entry, entry.getSbn()));
     }
 
     @Test
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 8f1b6017..66c01ca 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
@@ -61,7 +61,9 @@
 import android.testing.TestableLooper.RunWithLooper;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
+import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.widget.LinearLayout;
 
 import androidx.test.filters.SmallTest;
 
@@ -70,6 +72,7 @@
 import com.android.internal.logging.testing.FakeMetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.Dependency;
 import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.InitController;
@@ -82,8 +85,6 @@
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.doze.DozeEvent;
-import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
@@ -91,6 +92,7 @@
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationEntryBuilder;
@@ -107,7 +109,7 @@
 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.NewNotifPipeline;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -141,9 +143,8 @@
 import java.io.ByteArrayOutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
+
+import dagger.Lazy;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -156,6 +157,7 @@
     private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
     private CommandQueue mCommandQueue;
 
+    @Mock private FeatureFlags mFeatureFlags;
     @Mock private LightBarController mLightBarController;
     @Mock private StatusBarIconController mStatusBarIconController;
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -169,6 +171,7 @@
     @Mock private ScrimController mScrimController;
     @Mock private DozeScrimController mDozeScrimController;
     @Mock private ArrayList<NotificationEntry> mNotificationList;
+    @Mock private Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
     @Mock private BiometricUnlockController mBiometricUnlockController;
     @Mock private NotificationData mNotificationData;
     @Mock private NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
@@ -205,7 +208,7 @@
     @Mock private KeyguardBypassController mKeyguardBypassController;
     @Mock private InjectionInflationController mInjectionInflationController;
     @Mock private DynamicPrivacyController mDynamicPrivacyController;
-    @Mock private NotifPipelineInitializer mNotifPipelineInitializer;
+    @Mock private NewNotifPipeline mNewNotifPipeline;
     @Mock private ZenModeController mZenModeController;
     @Mock private AutoHideController mAutoHideController;
     @Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
@@ -221,11 +224,17 @@
     @Mock private StatusBarWindowViewController mStatusBarWindowViewController;
     @Mock private NotifLog mNotifLog;
     @Mock private DozeParameters mDozeParameters;
+    @Mock private Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
+    @Mock private LockscreenWallpaper mLockscreenWallpaper;
+    @Mock private DozeServiceHost mDozeServiceHost;
+    @Mock private LinearLayout mLockIconContainer;
+    @Mock private ViewMediatorCallback mKeyguardVieMediatorCallback;
 
     @Before
     public void setup() throws Exception {
         MockitoAnnotations.initMocks(this);
         mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter);
+        mDependency.injectMockDependency(KeyguardDismissUtil.class);
 
         IPowerManager powerManagerService = mock(IPowerManager.class);
         mPowerManager = new PowerManager(mContext, powerManagerService,
@@ -286,8 +295,12 @@
         when(mStatusBarWindowViewControllerBuilder.build())
                 .thenReturn(mStatusBarWindowViewController);
 
+        when(mLockscreenWallpaperLazy.get()).thenReturn(mLockscreenWallpaper);
+        when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController);
+
         mStatusBar = new StatusBar(
                 mContext,
+                mFeatureFlags,
                 mLightBarController,
                 mAutoHideController,
                 mKeyguardUpdateMonitor,
@@ -302,7 +315,7 @@
                 mDynamicPrivacyController,
                 mBypassHeadsUpNotifier,
                 true,
-                mNotifPipelineInitializer,
+                () -> mNewNotifPipeline,
                 new FalsingManagerFake(),
                 mBroadcastDispatcher,
                 new RemoteInputQuickSettingsDisabler(
@@ -345,24 +358,39 @@
                 mStatusBarWindowController,
                 mStatusBarWindowViewControllerBuilder,
                 mNotifLog,
-                mDozeParameters);
+                mDozeParameters,
+                mScrimController,
+                mLockscreenWallpaperLazy,
+                mBiometricUnlockControllerLazy,
+                mDozeServiceHost,
+                mPowerManager,
+                mDozeScrimController);
+
+        when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
+                mLockIconContainer);
+
+        when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
+                any(NotificationPanelView.class), any(BiometricUnlockController.class),
+                any(ViewGroup.class), any(ViewGroup.class), any(KeyguardBypassController.class)))
+                .thenReturn(mStatusBarKeyguardViewManager);
+
+        when(mKeyguardViewMediator.getViewMediatorCallback()).thenReturn(
+                mKeyguardVieMediatorCallback);
+
         // TODO: we should be able to call mStatusBar.start() and have all the below values
         // initialized automatically.
         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.mStatusBarWindowViewController = mStatusBarWindowViewController;
+        mStatusBar.startKeyguard();
         mStatusBar.putComponent(StatusBar.class, mStatusBar);
         Dependency.get(InitController.class).executePostInitTasks();
         entryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller,
@@ -727,83 +755,18 @@
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
         mStatusBar.showKeyguardImpl();
 
-        // Keep track of callback to be able to stop the pulse
-        DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1];
-        doAnswer(invocation -> {
-            pulseCallback[0] = invocation.getArgument(0);
-            return null;
-        }).when(mDozeScrimController).pulse(any(), anyInt());
-
         // Starting a pulse should change the scrim controller to the pulsing state
-        mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class),
-                DozeEvent.PULSE_REASON_NOTIFICATION);
+        when(mDozeServiceHost.isPulsing()).thenReturn(true);
+        mStatusBar.updateScrimController();
         verify(mScrimController).transitionTo(eq(ScrimState.PULSING), any());
 
         // Ending a pulse should take it back to keyguard state
-        pulseCallback[0].onPulseFinished();
+        when(mDozeServiceHost.isPulsing()).thenReturn(false);
+        mStatusBar.updateScrimController();
         verify(mScrimController).transitionTo(eq(ScrimState.KEYGUARD));
     }
 
     @Test
-    public void testPulseWhileDozing_notifyAuthInterrupt() {
-        HashSet<Integer> reasonsWantingAuth = new HashSet<>(
-                Collections.singletonList(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN));
-        HashSet<Integer> reasonsSkippingAuth = new HashSet<>(
-                Arrays.asList(DozeEvent.PULSE_REASON_INTENT,
-                        DozeEvent.PULSE_REASON_NOTIFICATION,
-                        DozeEvent.PULSE_REASON_SENSOR_SIGMOTION,
-                        DozeEvent.REASON_SENSOR_PICKUP,
-                        DozeEvent.REASON_SENSOR_DOUBLE_TAP,
-                        DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS,
-                        DozeEvent.PULSE_REASON_DOCKING,
-                        DozeEvent.REASON_SENSOR_WAKE_UP,
-                        DozeEvent.REASON_SENSOR_TAP));
-        HashSet<Integer> reasonsThatDontPulse = new HashSet<>(
-                Arrays.asList(DozeEvent.REASON_SENSOR_PICKUP,
-                        DozeEvent.REASON_SENSOR_DOUBLE_TAP,
-                        DozeEvent.REASON_SENSOR_TAP));
-
-        doAnswer(invocation -> {
-            DozeHost.PulseCallback callback = invocation.getArgument(0);
-            callback.onPulseStarted();
-            return null;
-        }).when(mDozeScrimController).pulse(any(), anyInt());
-
-        mStatusBar.mDozeServiceHost.mWakeLockScreenPerformsAuth = true;
-        for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) {
-            reset(mKeyguardUpdateMonitor);
-            mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), i);
-            if (reasonsWantingAuth.contains(i)) {
-                verify(mKeyguardUpdateMonitor).onAuthInterruptDetected(eq(true));
-            } else if (reasonsSkippingAuth.contains(i) || reasonsThatDontPulse.contains(i)) {
-                verify(mKeyguardUpdateMonitor, never()).onAuthInterruptDetected(eq(true));
-            } else {
-                throw new AssertionError("Reason " + i + " isn't specified as wanting or skipping"
-                        + " passive auth. Please consider how this pulse reason should behave.");
-            }
-        }
-    }
-
-    @Test
-    public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() {
-        // Keep track of callback to be able to stop the pulse
-        final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1];
-        doAnswer(invocation -> {
-            pulseCallback[0] = invocation.getArgument(0);
-            return null;
-        }).when(mDozeScrimController).pulse(any(), anyInt());
-
-        // Starting a pulse while docking should suppress wakeup gesture
-        mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class),
-                DozeEvent.PULSE_REASON_DOCKING);
-        verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(true));
-
-        // Ending a pulse should restore wakeup gesture
-        pulseCallback[0].onPulseFinished();
-        verify(mStatusBarWindowViewController).suppressWakeUpGesture(eq(false));
-    }
-
-    @Test
     public void testSetState_changesIsFullScreenUserSwitcherState() {
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
         assertFalse(mStatusBar.isFullScreenUserSwitcherState());
@@ -829,27 +792,17 @@
     }
 
     @Test
-    public void testStartStopDozing() {
-        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
-        when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
-
-        mStatusBar.mDozeServiceHost.startDozing();
-        verify(mStatusBarStateController).setIsDozing(eq(true));
-
-        mStatusBar.mDozeServiceHost.stopDozing();
-        verify(mStatusBarStateController).setIsDozing(eq(false));
-    }
-
-    @Test
     public void testOnStartedWakingUp_isNotDozing() {
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
         when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
-        mStatusBar.mDozeServiceHost.startDozing();
-        verify(mStatusBarStateController).setIsDozing(eq(true));
+        when(mDozeServiceHost.getDozingRequested()).thenReturn(true);
+        mStatusBar.updateIsKeyguard();
+        // TODO: mNotificationPanelView.expand(false) gets called twice. Should be once.
+        verify(mNotificationPanelView, times(2)).expand(eq(false));
         clearInvocations(mNotificationPanelView);
 
         mStatusBar.mWakefulnessObserver.onStartedWakingUp();
-        verify(mStatusBarStateController).setIsDozing(eq(false));
+        verify(mDozeServiceHost).stopDozing();
         verify(mNotificationPanelView).expand(eq(false));
     }
 
@@ -857,7 +810,8 @@
     public void testOnStartedWakingUp_doesNotDismissBouncer_whenPulsing() {
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
         when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
-        mStatusBar.mDozeServiceHost.startDozing();
+        when(mDozeServiceHost.getDozingRequested()).thenReturn(true);
+        mStatusBar.updateIsKeyguard();
         clearInvocations(mNotificationPanelView);
 
         mStatusBar.setBouncerShowing(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
index 6b83fed..fc7d0ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -73,7 +73,7 @@
                 .getRecommendedTimeoutMillis(anyInt(), anyInt());
         mHeadsUpManager.showNotification(mEntry);
         Runnable pastNormalTimeRunnable =
-                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.key);
+                () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.getKey());
         mTestHandler.postDelayed(pastNormalTimeRunnable,
                         (TEST_A11Y_AUTO_DISMISS_TIME + TEST_AUTO_DISMISS_TIME) / 2);
         mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_A11Y_TIMEOUT_TIME);
@@ -82,7 +82,7 @@
 
         assertFalse("Test timed out", mTimedOut);
         assertTrue("Heads up should live long enough", mLivesPastNormalTime);
-        assertFalse(mHeadsUpManager.isAlerting(mEntry.key));
+        assertFalse(mHeadsUpManager.isAlerting(mEntry.getKey()));
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
index d7df96d..54cb0b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java
@@ -16,14 +16,14 @@
 
 package com.android.systemui.util.sensors;
 
-import android.content.Context;
+import android.content.res.Resources;
 
 public class FakeProximitySensor extends ProximitySensor {
     private boolean mAvailable;
     private boolean mPaused;
 
-    public FakeProximitySensor(Context context, AsyncSensorManager sensorManager) {
-        super(context, sensorManager);
+    public FakeProximitySensor(Resources resources, AsyncSensorManager sensorManager) {
+        super(resources, sensorManager);
 
         mAvailable = true;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
index 1deb495..0bc7868a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
@@ -92,6 +92,18 @@
         if (s != null) {
             return s;
         }
+        switch(type) {
+            case Sensor.TYPE_PROXIMITY:
+                try {
+                    return createSensor(Sensor.TYPE_PROXIMITY, null);
+                } catch (Exception e) {
+                    // fall through
+                }
+                break;
+            default:
+                break;
+
+        }
         // Our mock sensors aren't wakeup, and it's a pain to create them that way. Instead, just
         // return non-wakeup sensors if we can't find a wakeup sensor.
         return getDefaultSensor(type, false /* wakeup */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
index fa943e3..37b315f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorTest.java
@@ -47,7 +47,7 @@
         AsyncSensorManager asyncSensorManager = new AsyncSensorManager(
                 sensorManager, null, new Handler());
         mFakeProximitySensor = sensorManager.getFakeProximitySensor();
-        mProximitySensor = new ProximitySensor(getContext(), asyncSensorManager);
+        mProximitySensor = new ProximitySensor(getContext().getResources(), asyncSensorManager);
     }
 
     @Test
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
new file mode 100644
index 0000000..ca69c18
--- /dev/null
+++ b/packages/Tethering/Android.bp
@@ -0,0 +1,79 @@
+//
+// 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.
+//
+
+java_defaults {
+    name: "TetheringAndroidLibraryDefaults",
+    platform_apis: true,
+    srcs: [
+        "src/**/*.java",
+        ":framework-tethering-shared-srcs",
+        ":services-tethering-shared-srcs",
+    ],
+    static_libs: [
+        "androidx.annotation_annotation",
+        "netd_aidl_interface-java",
+        "networkstack-aidl-interfaces-java",
+        "tethering-client",
+    ],
+    manifest: "AndroidManifestBase.xml",
+}
+
+// Build tethering static library, used to compile both variants of the tethering.
+android_library {
+    name: "TetheringApiCurrentLib",
+    defaults: ["TetheringAndroidLibraryDefaults"],
+}
+
+// Common defaults for compiling the actual APK.
+java_defaults {
+    name: "TetheringAppDefaults",
+    platform_apis: true,
+    privileged: true,
+    resource_dirs: [
+        "res",
+    ],
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+}
+
+// Non-updatable tethering running in the system server process for devices not using the module
+// TODO: build in-process tethering APK here.
+
+// Updatable tethering packaged as an application
+android_app {
+    name: "Tethering",
+    defaults: ["TetheringAppDefaults"],
+    static_libs: ["TetheringApiCurrentLib"],
+    certificate: "networkstack",
+    manifest: "AndroidManifest.xml",
+    use_embedded_native_libs: true,
+    // The permission configuration *must* be included to ensure security of the device
+    required: ["NetworkPermissionConfig"],
+}
+
+// This group will be removed when tethering migration is done.
+filegroup {
+    name: "tethering-services-srcs",
+    srcs: [
+        "src/com/android/server/connectivity/tethering/TetheringConfiguration.java",
+        "src/android/net/dhcp/DhcpServerCallbacks.java",
+        "src/android/net/dhcp/DhcpServingParamsParcelExt.java",
+        "src/android/net/ip/IpServer.java",
+        "src/android/net/ip/RouterAdvertisementDaemon.java",
+        "src/android/net/util/InterfaceSet.java",
+    ],
+}
diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml
new file mode 100644
index 0000000..eb51593
--- /dev/null
+++ b/packages/Tethering/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.tethering"
+          android:sharedUserId="android.uid.networkstack">
+    <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+
+    <application
+        android:process="com.android.networkstack.process"
+        android:extractNativeLibs="false"
+        android:persistent="true">
+    </application>
+</manifest>
diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml
new file mode 100644
index 0000000..b9cac19
--- /dev/null
+++ b/packages/Tethering/AndroidManifestBase.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.tethering"
+          android:versionCode="1"
+          android:versionName="R-initial">
+    <application
+        android:label="Tethering"
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true"
+        android:usesCleartextTraffic="true">
+    </application>
+</manifest>
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
new file mode 100644
index 0000000..5b01b1e
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+// AIDL interfaces between the core system and the tethering mainline module.
+aidl_interface {
+    name: "tethering-aidl-interfaces",
+    local_include_dir: "src",
+    srcs: [
+        "src/android/net/ITetheringConnector.aidl",
+    ],
+    backend: {
+        ndk: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+    },
+}
+
+java_library {
+    name: "tethering-client",
+    platform_apis: true,
+    static_libs: [
+        "tethering-aidl-interfaces-java",
+    ],
+}
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
similarity index 62%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
index d2ec357..443481e 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
@@ -1,19 +1,20 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
+/**
+ * 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
+ *     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
+ * See the License for the specific language governing perNmissions and
  * limitations under the License.
  */
+package android.net;
 
-package android.app.timedetector;
-
-parcelable TimeSignal;
\ No newline at end of file
+/** @hide */
+oneway interface ITetheringConnector {
+}
diff --git a/packages/Tethering/proguard.flags b/packages/Tethering/proguard.flags
new file mode 100644
index 0000000..77fc024
--- /dev/null
+++ b/packages/Tethering/proguard.flags
@@ -0,0 +1 @@
+#TBD
diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml
new file mode 100644
index 0000000..37e679d
--- /dev/null
+++ b/packages/Tethering/res/values/config.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!--
+    OEMs that wish to change the below settings must do so via a runtime resource overlay package
+    and *NOT* by changing this file. This file is part of the tethering mainline module.
+    -->
+</resources>
diff --git a/services/net/java/android/net/dhcp/DhcpServerCallbacks.java b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
similarity index 100%
rename from services/net/java/android/net/dhcp/DhcpServerCallbacks.java
rename to packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
diff --git a/services/net/java/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
similarity index 100%
rename from services/net/java/android/net/dhcp/DhcpServingParamsParcelExt.java
rename to packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java
diff --git a/services/net/java/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
similarity index 93%
rename from services/net/java/android/net/ip/IpServer.java
rename to packages/Tethering/src/android/net/ip/IpServer.java
index 6a6a130..ff3d7bc 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -16,7 +16,7 @@
 
 package android.net.ip;
 
-import static android.net.NetworkUtils.numericToInetAddress;
+import static android.net.InetAddresses.parseNumericAddress;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.util.NetworkConstants.FF;
 import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
@@ -77,6 +77,7 @@
     public static final int STATE_TETHERED    = 2;
     public static final int STATE_LOCAL_ONLY  = 3;
 
+    /** Get string name of |state|.*/
     public static String getStateString(int state) {
         switch (state) {
             case STATE_UNAVAILABLE: return "UNAVAILABLE";
@@ -93,6 +94,8 @@
     private static final int USB_PREFIX_LENGTH = 24;
     private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1";
     private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
+    private static final String WIFI_P2P_IFACE_ADDR = "192.168.49.1";
+    private static final int WIFI_P2P_IFACE_PREFIX_LENGTH = 24;
 
     // TODO: have PanService use some visible version of this constant
     private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
@@ -101,15 +104,16 @@
     // TODO: have this configurable
     private static final int DHCP_LEASE_TIME_SECS = 3600;
 
-    private final static String TAG = "IpServer";
-    private final static boolean DBG = false;
-    private final static boolean VDBG = false;
-    private static final Class[] messageClasses = {
+    private static final String TAG = "IpServer";
+    private static final boolean DBG = false;
+    private static final boolean VDBG = false;
+    private static final Class[] sMessageClasses = {
             IpServer.class
     };
     private static final SparseArray<String> sMagicDecoderRing =
-            MessageUtils.findMessageNames(messageClasses);
+            MessageUtils.findMessageNames(sMessageClasses);
 
+    /** IpServer callback. */
     public static class Callback {
         /**
          * Notify that |who| has changed its tethering state.
@@ -129,11 +133,14 @@
         public void updateLinkProperties(IpServer who, LinkProperties newLp) {}
     }
 
+    /** Capture IpServer dependencies, for injection. */
     public static class Dependencies {
+        /** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
         public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
             return new RouterAdvertisementDaemon(ifParams);
         }
 
+        /** Get |ifName|'s interface information.*/
         public InterfaceParams getInterfaceParams(String ifName) {
             return InterfaceParams.getByName(ifName);
         }
@@ -242,25 +249,51 @@
         setInitialState(mInitialState);
     }
 
-    public String interfaceName() { return mIfaceName; }
-
-    public int interfaceType() { return mInterfaceType; }
-
-    public int lastError() { return mLastError; }
-
-    public int servingMode() { return mServingMode; }
-
-    public LinkProperties linkProperties() { return new LinkProperties(mLinkProperties); }
-
-    public void stop() { sendMessage(CMD_INTERFACE_DOWN); }
-
-    public void unwanted() { sendMessage(CMD_TETHER_UNREQUESTED); }
+    /** Interface name which IpServer served.*/
+    public String interfaceName() {
+        return mIfaceName;
+    }
 
     /**
-     * Internals.
+     * Tethering downstream type. It would be one of ConnectivityManager#TETHERING_*.
      */
+    public int interfaceType() {
+        return mInterfaceType;
+    }
 
-    private boolean startIPv4() { return configureIPv4(true); }
+    /** Last error from this IpServer. */
+    public int lastError() {
+        return mLastError;
+    }
+
+    /** Serving mode is the current state of IpServer state machine. */
+    public int servingMode() {
+        return mServingMode;
+    }
+
+    /** The properties of the network link which IpServer is serving. */
+    public LinkProperties linkProperties() {
+        return new LinkProperties(mLinkProperties);
+    }
+
+    /** Stop this IpServer. After this is called this IpServer should not be used any more. */
+    public void stop() {
+        sendMessage(CMD_INTERFACE_DOWN);
+    }
+
+    /**
+     * Tethering is canceled. IpServer state machine will be available and wait for
+     * next tethering request.
+     */
+    public void unwanted() {
+        sendMessage(CMD_TETHER_UNREQUESTED);
+    }
+
+    /** Internals. */
+
+    private boolean startIPv4() {
+        return configureIPv4(true);
+    }
 
     /**
      * Convenience wrapper around INetworkStackStatusCallback to run callbacks on the IpServer
@@ -403,9 +436,12 @@
         } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
             ipAsString = getRandomWifiIPv4Address();
             prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
+        } else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
+            ipAsString = WIFI_P2P_IFACE_ADDR;
+            prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
         } else {
             // BT configures the interface elsewhere: only start DHCP.
-            final Inet4Address srvAddr = (Inet4Address) numericToInetAddress(BLUETOOTH_IFACE_ADDR);
+            final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
             return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
         }
 
@@ -417,7 +453,7 @@
                 return false;
             }
 
-            InetAddress addr = numericToInetAddress(ipAsString);
+            InetAddress addr = parseNumericAddress(ipAsString);
             linkAddr = new LinkAddress(addr, prefixLen);
             ifcg.setLinkAddress(linkAddr);
             if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
@@ -468,7 +504,7 @@
 
     private String getRandomWifiIPv4Address() {
         try {
-            byte[] bytes = numericToInetAddress(WIFI_HOST_IFACE_ADDR).getAddress();
+            byte[] bytes = parseNumericAddress(WIFI_HOST_IFACE_ADDR).getAddress();
             bytes[3] = getRandomSanitizedByte(DOUG_ADAMS, asByte(0), asByte(1), FF);
             return InetAddress.getByAddress(bytes).getHostAddress();
         } catch (Exception e) {
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
similarity index 88%
rename from services/net/java/android/net/ip/RouterAdvertisementDaemon.java
rename to packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index 59aea21..4147413 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/packages/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -119,6 +119,7 @@
     private volatile MulticastTransmitter mMulticastTransmitter;
     private volatile UnicastResponder mUnicastResponder;
 
+    /** Encapsulate the RA parameters for RouterAdvertisementDaemon.*/
     public static class RaParams {
         // Tethered traffic will have the hop limit properly decremented.
         // Consequently, set the hoplimit greater by one than the upstream
@@ -150,10 +151,12 @@
             dnses = (HashSet) other.dnses.clone();
         }
 
-        // Returns the subset of RA parameters that become deprecated when
-        // moving from announcing oldRa to announcing newRa.
-        //
-        // Currently only tracks differences in |prefixes| and |dnses|.
+        /**
+         * Returns the subset of RA parameters that become deprecated when
+         * moving from announcing oldRa to announcing newRa.
+         *
+         * Currently only tracks differences in |prefixes| and |dnses|.
+         */
         public static RaParams getDeprecatedRaParams(RaParams oldRa, RaParams newRa) {
             RaParams newlyDeprecated = new RaParams();
 
@@ -179,7 +182,9 @@
         private final HashMap<IpPrefix, Integer> mPrefixes = new HashMap<>();
         private final HashMap<Inet6Address, Integer> mDnses = new HashMap<>();
 
-        Set<IpPrefix> getPrefixes() { return mPrefixes.keySet(); }
+        Set<IpPrefix> getPrefixes() {
+            return mPrefixes.keySet();
+        }
 
         void putPrefixes(Set<IpPrefix> prefixes) {
             for (IpPrefix ipp : prefixes) {
@@ -193,7 +198,9 @@
             }
         }
 
-        Set<Inet6Address> getDnses() { return mDnses.keySet(); }
+        Set<Inet6Address> getDnses() {
+            return mDnses.keySet();
+        }
 
         void putDnses(Set<Inet6Address> dnses) {
             for (Inet6Address dns : dnses) {
@@ -207,7 +214,9 @@
             }
         }
 
-        boolean isEmpty() { return mPrefixes.isEmpty() && mDnses.isEmpty(); }
+        boolean isEmpty() {
+            return mPrefixes.isEmpty() && mDnses.isEmpty();
+        }
 
         private boolean decrementCounters() {
             boolean removed = decrementCounter(mPrefixes);
@@ -219,7 +228,7 @@
             boolean removed = false;
 
             for (Iterator<Map.Entry<T, Integer>> it = map.entrySet().iterator();
-                 it.hasNext();) {
+                    it.hasNext();) {
                 Map.Entry<T, Integer> kv = it.next();
                 if (kv.getValue() == 0) {
                     it.remove();
@@ -240,6 +249,7 @@
         mDeprecatedInfoTracker = new DeprecatedInfoTracker();
     }
 
+    /** Build new RA.*/
     public void buildNewRa(RaParams deprecatedParams, RaParams newParams) {
         synchronized (mLock) {
             if (deprecatedParams != null) {
@@ -260,6 +270,7 @@
         maybeNotifyMulticastTransmitter();
     }
 
+    /** Start router advertisement daemon. */
     public boolean start() {
         if (!createSocket()) {
             return false;
@@ -274,6 +285,7 @@
         return true;
     }
 
+    /** Stop router advertisement daemon. */
     public void stop() {
         closeSocket();
         // Wake up mMulticastTransmitter thread to interrupt a potential 1 day sleep before
@@ -362,8 +374,12 @@
         }
     }
 
-    private static byte asByte(int value) { return (byte) value; }
-    private static short asShort(int value) { return (short) value; }
+    private static byte asByte(int value) {
+        return (byte) value;
+    }
+    private static short asShort(int value) {
+        return (short) value;
+    }
 
     private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute, byte hopLimit) {
         /**
@@ -384,14 +400,14 @@
             +-+-+-+-+-+-+-+-+-+-+-+-
         */
         ra.put(ICMPV6_ND_ROUTER_ADVERT)
-          .put(asByte(0))
-          .putShort(asShort(0))
-          .put(hopLimit)
-          // RFC 4191 "high" preference, iff. advertising a default route.
-          .put(hasDefaultRoute ? asByte(0x08) : asByte(0))
-          .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0))
-          .putInt(0)
-          .putInt(0);
+                .put(asByte(0))
+                .putShort(asShort(0))
+                .put(hopLimit)
+                // RFC 4191 "high" preference, iff. advertising a default route.
+                .put(hasDefaultRoute ? asByte(0x08) : asByte(0))
+                .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0))
+                .putInt(0)
+                .putInt(0);
     }
 
     private static void putSlla(ByteBuffer ra, byte[] slla) {
@@ -408,11 +424,12 @@
             // Only IEEE 802.3 6-byte addresses are supported.
             return;
         }
-        final byte ND_OPTION_SLLA = 1;
-        final byte SLLA_NUM_8OCTETS = 1;
-        ra.put(ND_OPTION_SLLA)
-          .put(SLLA_NUM_8OCTETS)
-          .put(slla);
+
+        final byte nd_option_slla = 1;
+        final byte slla_num_8octets = 1;
+        ra.put(nd_option_slla)
+            .put(slla_num_8octets)
+            .put(slla);
     }
 
     private static void putExpandedFlagsOption(ByteBuffer ra) {
@@ -428,13 +445,13 @@
             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
          */
 
-        final byte ND_OPTION_EFO = 26;
-        final byte EFO_NUM_8OCTETS = 1;
+        final byte nd_option__efo = 26;
+        final byte efo_num_8octets = 1;
 
-        ra.put(ND_OPTION_EFO)
-          .put(EFO_NUM_8OCTETS)
-          .putShort(asShort(0))
-          .putInt(0);
+        ra.put(nd_option__efo)
+            .put(efo_num_8octets)
+            .putShort(asShort(0))
+            .putInt(0);
     }
 
     private static void putMtu(ByteBuffer ra, int mtu) {
@@ -449,12 +466,12 @@
             |                              MTU                              |
             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         */
-        final byte ND_OPTION_MTU = 5;
-        final byte MTU_NUM_8OCTETS = 1;
-        ra.put(ND_OPTION_MTU)
-          .put(MTU_NUM_8OCTETS)
-          .putShort(asShort(0))
-          .putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu);
+        final byte nd_option_mtu = 5;
+        final byte mtu_num_8octs = 1;
+        ra.put(nd_option_mtu)
+            .put(mtu_num_8octs)
+            .putShort(asShort(0))
+            .putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu);
     }
 
     private static void putPio(ByteBuffer ra, IpPrefix ipp,
@@ -486,22 +503,22 @@
         if (prefixLength != 64) {
             return;
         }
-        final byte ND_OPTION_PIO = 3;
-        final byte PIO_NUM_8OCTETS = 4;
+        final byte nd_option_pio = 3;
+        final byte pio_num_8octets = 4;
 
         if (validTime < 0) validTime = 0;
         if (preferredTime < 0) preferredTime = 0;
         if (preferredTime > validTime) preferredTime = validTime;
 
         final byte[] addr = ipp.getAddress().getAddress();
-        ra.put(ND_OPTION_PIO)
-          .put(PIO_NUM_8OCTETS)
-          .put(asByte(prefixLength))
-          .put(asByte(0xc0)) /* L & A set */
-          .putInt(validTime)
-          .putInt(preferredTime)
-          .putInt(0)
-          .put(addr);
+        ra.put(nd_option_pio)
+            .put(pio_num_8octets)
+            .put(asByte(prefixLength))
+            .put(asByte(0xc0)) /* L & A set */
+            .putInt(validTime)
+            .putInt(preferredTime)
+            .putInt(0)
+            .put(addr);
     }
 
     private static void putRio(ByteBuffer ra, IpPrefix ipp) {
@@ -524,16 +541,16 @@
         if (prefixLength > 64) {
             return;
         }
-        final byte ND_OPTION_RIO = 24;
-        final byte RIO_NUM_8OCTETS = asByte(
+        final byte nd_option_rio = 24;
+        final byte rio_num_8octets = asByte(
                 (prefixLength == 0) ? 1 : (prefixLength <= 8) ? 2 : 3);
 
         final byte[] addr = ipp.getAddress().getAddress();
-        ra.put(ND_OPTION_RIO)
-          .put(RIO_NUM_8OCTETS)
-          .put(asByte(prefixLength))
-          .put(asByte(0x18))
-          .putInt(DEFAULT_LIFETIME);
+        ra.put(nd_option_rio)
+            .put(rio_num_8octets)
+            .put(asByte(prefixLength))
+            .put(asByte(0x18))
+            .putInt(DEFAULT_LIFETIME);
 
         // Rely upon an IpPrefix's address being properly zeroed.
         if (prefixLength > 0) {
@@ -566,12 +583,12 @@
         }
         if (filteredDnses.isEmpty()) return;
 
-        final byte ND_OPTION_RDNSS = 25;
-        final byte RDNSS_NUM_8OCTETS = asByte(dnses.size() * 2 + 1);
-        ra.put(ND_OPTION_RDNSS)
-          .put(RDNSS_NUM_8OCTETS)
-          .putShort(asShort(0))
-          .putInt(lifetime);
+        final byte nd_option_rdnss = 25;
+        final byte rdnss_num_8octets = asByte(dnses.size() * 2 + 1);
+        ra.put(nd_option_rdnss)
+            .put(rdnss_num_8octets)
+            .putShort(asShort(0))
+            .putInt(lifetime);
 
         for (Inet6Address dns : filteredDnses) {
             // NOTE: If the full of list DNS servers doesn't fit in the packet,
@@ -585,7 +602,7 @@
     }
 
     private boolean createSocket() {
-        final int SEND_TIMEOUT_MS = 300;
+        final int send_timout_ms = 300;
 
         final int oldTag = TrafficStats.getAndSetThreadStatsTag(
                 TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR);
@@ -593,7 +610,7 @@
             mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
             // Setting SNDTIMEO is purely for defensive purposes.
             Os.setsockoptTimeval(
-                    mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
+                    mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(send_timout_ms));
             Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
             NetworkUtils.protectFromVpn(mSocket);
             NetworkUtils.setupRaSocket(mSocket, mInterface.index);
@@ -611,7 +628,7 @@
         if (mSocket != null) {
             try {
                 IoBridge.closeAndSignalBlockedThreads(mSocket);
-            } catch (IOException ignored) {}
+            } catch (IOException ignored) { }
         }
         mSocket = null;
     }
@@ -627,9 +644,9 @@
         }
 
         final InetAddress destip = dest.getAddress();
-        return (destip instanceof Inet6Address) &&
-                destip.isLinkLocalAddress() &&
-               (((Inet6Address) destip).getScopeId() == mInterface.index);
+        return (destip instanceof Inet6Address)
+               && destip.isLinkLocalAddress()
+               && (((Inet6Address) destip).getScopeId() == mInterface.index);
     }
 
     private void maybeSendRA(InetSocketAddress dest) {
@@ -654,11 +671,11 @@
     }
 
     private final class UnicastResponder extends Thread {
-        private final InetSocketAddress solicitor = new InetSocketAddress();
+        private final InetSocketAddress mSolicitor = new InetSocketAddress();
         // The recycled buffer for receiving Router Solicitations from clients.
         // If the RS is larger than IPV6_MIN_MTU the packets are truncated.
         // This is fine since currently only byte 0 is examined anyway.
-        private final byte mSolication[] = new byte[IPV6_MIN_MTU];
+        private final byte[] mSolicitation = new byte[IPV6_MIN_MTU];
 
         @Override
         public void run() {
@@ -666,9 +683,9 @@
                 try {
                     // Blocking receive.
                     final int rval = Os.recvfrom(
-                            mSocket, mSolication, 0, mSolication.length, 0, solicitor);
+                            mSocket, mSolicitation, 0, mSolicitation.length, 0, mSolicitor);
                     // Do the least possible amount of validation.
-                    if (rval < 1 || mSolication[0] != ICMPV6_ND_ROUTER_SOLICIT) {
+                    if (rval < 1 || mSolicitation[0] != ICMPV6_ND_ROUTER_SOLICIT) {
                         continue;
                     }
                 } catch (ErrnoException | SocketException e) {
@@ -678,7 +695,7 @@
                     continue;
                 }
 
-                maybeSendRA(solicitor);
+                maybeSendRA(mSolicitor);
             }
         }
     }
diff --git a/services/net/java/android/net/util/InterfaceSet.java b/packages/Tethering/src/android/net/util/InterfaceSet.java
similarity index 95%
rename from services/net/java/android/net/util/InterfaceSet.java
rename to packages/Tethering/src/android/net/util/InterfaceSet.java
index 9f26fa1..7589787 100644
--- a/services/net/java/android/net/util/InterfaceSet.java
+++ b/packages/Tethering/src/android/net/util/InterfaceSet.java
@@ -47,6 +47,6 @@
     public boolean equals(Object obj) {
         return obj != null
                 && obj instanceof InterfaceSet
-                && ifnames.equals(((InterfaceSet)obj).ifnames);
+                && ifnames.equals(((InterfaceSet) obj).ifnames);
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
similarity index 91%
rename from services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
rename to packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 1907892..7709727 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -28,6 +28,7 @@
 import static com.android.internal.R.array.config_tether_dhcp_range;
 import static com.android.internal.R.array.config_tether_upstream_types;
 import static com.android.internal.R.array.config_tether_usb_regexs;
+import static com.android.internal.R.array.config_tether_wifi_p2p_regexs;
 import static com.android.internal.R.array.config_tether_wifi_regexs;
 import static com.android.internal.R.bool.config_tether_upstream_automatic;
 import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period;
@@ -81,10 +82,11 @@
         "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
     };
 
-    private final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
+    private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"};
 
     public final String[] tetherableUsbRegexs;
     public final String[] tetherableWifiRegexs;
+    public final String[] tetherableWifiP2pRegexs;
     public final String[] tetherableBluetoothRegexs;
     public final boolean isDunRequired;
     public final boolean chooseUpstreamAutomatically;
@@ -110,6 +112,7 @@
         // us an interface name. Careful consideration needs to be given to
         // implications for Settings and for provisioning checks.
         tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
+        tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs);
         tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
 
         isDunRequired = checkDunRequired(ctx, subId);
@@ -130,28 +133,44 @@
         configLog.log(toString());
     }
 
+    /** Check whether input interface belong to usb.*/
     public boolean isUsb(String iface) {
         return matchesDownstreamRegexs(iface, tetherableUsbRegexs);
     }
 
+    /** Check whether input interface belong to wifi.*/
     public boolean isWifi(String iface) {
         return matchesDownstreamRegexs(iface, tetherableWifiRegexs);
     }
 
+    /** Check whether this interface is Wifi P2P interface. */
+    public boolean isWifiP2p(String iface) {
+        return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs);
+    }
+
+    /** Check whether using legacy mode for wifi P2P. */
+    public boolean isWifiP2pLegacyTetheringMode() {
+        return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0);
+    }
+
+    /** Check whether input interface belong to bluetooth.*/
     public boolean isBluetooth(String iface) {
         return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
     }
 
+    /** Check whether no ui entitlement application is available.*/
     public boolean hasMobileHotspotProvisionApp() {
         return !TextUtils.isEmpty(provisioningAppNoUi);
     }
 
+    /** Does the dumping.*/
     public void dump(PrintWriter pw) {
         pw.print("subId: ");
         pw.println(subId);
 
         dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
         dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
+        dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs);
         dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
 
         pw.print("isDunRequired: ");
@@ -173,11 +192,13 @@
         pw.println(enableLegacyDhcpServer);
     }
 
+    /** Returns the string representation of this object.*/
     public String toString() {
         final StringJoiner sj = new StringJoiner(" ");
         sj.add(String.format("subId:%d", subId));
         sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
         sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
+        sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs)));
         sj.add(String.format("tetherableBluetoothRegexs:%s",
                 makeString(tetherableBluetoothRegexs)));
         sj.add(String.format("isDunRequired:%s", isDunRequired));
@@ -196,7 +217,7 @@
 
         if (values != null) {
             final StringJoiner sj = new StringJoiner(", ", "[", "]");
-            for (String value : values) { sj.add(value); }
+            for (String value : values) sj.add(value);
             pw.print(sj.toString());
         } else {
             pw.print("null");
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
new file mode 100644
index 0000000..da62107
--- /dev/null
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -0,0 +1,50 @@
+//
+// 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.
+//
+
+android_test {
+    name: "TetheringTests",
+    certificate: "platform",
+    srcs: ["src/**/*.java"],
+    test_suites: ["device-tests"],
+    static_libs: [
+        "androidx.test.rules",
+        "frameworks-base-testutils",
+        "mockito-target-extended-minus-junit4",
+        "TetheringApiCurrentLib",
+        "testables",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+    jni_libs: [
+        // For mockito extended
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
+}
+
+// This group would be removed when tethering migration is done.
+filegroup {
+    name: "tethering-tests-src",
+    srcs: [
+        "src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java",
+        "src/android/net/dhcp/DhcpServingParamsParcelExtTest.java",
+        "src/android/net/ip/IpServerTest.java",
+        "src/android/net/util/InterfaceSetTest.java",
+    ],
+}
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
new file mode 100644
index 0000000..049ff6d
--- /dev/null
+++ b/packages/Tethering/tests/unit/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.tethering.tests.unit">
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.tethering.tests.unit"
+        android:label="Tethering service tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/net/java/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
similarity index 100%
rename from tests/net/java/android/net/dhcp/DhcpServingParamsParcelExtTest.java
rename to packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java
diff --git a/tests/net/java/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
similarity index 93%
rename from tests/net/java/android/net/ip/IpServerTest.java
rename to packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 05912e8..4358cd6 100644
--- a/tests/net/java/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -19,11 +19,13 @@
 import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
 import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
 import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.ip.IpServer.STATE_AVAILABLE;
+import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
 import static android.net.ip.IpServer.STATE_TETHERED;
 import static android.net.ip.IpServer.STATE_UNAVAILABLE;
 import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
@@ -181,7 +183,7 @@
     @Test
     public void shouldDoNothingUntilRequested() throws Exception {
         initStateMachine(TETHERING_BLUETOOTH);
-        final int [] NOOP_COMMANDS = {
+        final int [] noOp_commands = {
             IpServer.CMD_TETHER_UNREQUESTED,
             IpServer.CMD_IP_FORWARDING_ENABLE_ERROR,
             IpServer.CMD_IP_FORWARDING_DISABLE_ERROR,
@@ -190,7 +192,7 @@
             IpServer.CMD_SET_DNS_FORWARDERS_ERROR,
             IpServer.CMD_TETHER_CONNECTION_CHANGED
         };
-        for (int command : NOOP_COMMANDS) {
+        for (int command : noOp_commands) {
             // None of these commands should trigger us to request action from
             // the rest of the system.
             dispatchCommand(command);
@@ -256,6 +258,23 @@
     }
 
     @Test
+    public void canBeTetheredAsWifiP2p() throws Exception {
+        initStateMachine(TETHERING_WIFI_P2P);
+
+        dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
+        InOrder inOrder = inOrder(mCallback, mNMService);
+        inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
+        inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
+        inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
+        inOrder.verify(mCallback).updateInterfaceState(
+                mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
+        inOrder.verify(mCallback).updateLinkProperties(
+                eq(mIpServer), mLinkPropertiesCaptor.capture());
+        assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
+        verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
+    }
+
+    @Test
     public void handlesFirstUpstreamChange() throws Exception {
         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
 
@@ -419,6 +438,14 @@
     }
 
     @Test
+    public void startsDhcpServerOnWifiP2p() throws Exception {
+        initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE);
+        dispatchTetherConnectionChanged(UPSTREAM_IFACE);
+
+        assertDhcpStarted(new IpPrefix("192.168.49.0/24"));
+    }
+
+    @Test
     public void doesNotStartDhcpServerIfDisabled() throws Exception {
         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
diff --git a/tests/net/java/android/net/util/InterfaceSetTest.java b/packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java
similarity index 100%
rename from tests/net/java/android/net/util/InterfaceSetTest.java
rename to packages/Tethering/tests/unit/src/android/net/util/InterfaceSetTest.java
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
similarity index 91%
rename from tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
rename to packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index e282963..9f9221f 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -24,7 +24,12 @@
 import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
+import static com.android.internal.R.array.config_mobile_hotspot_provision_app;
+import static com.android.internal.R.array.config_tether_bluetooth_regexs;
+import static com.android.internal.R.array.config_tether_dhcp_range;
 import static com.android.internal.R.array.config_tether_upstream_types;
+import static com.android.internal.R.array.config_tether_usb_regexs;
+import static com.android.internal.R.array.config_tether_wifi_regexs;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -86,7 +91,9 @@
         }
 
         @Override
-        public Resources getResources() { return mResources; }
+        public Resources getResources() {
+            return mResources;
+        }
 
         @Override
         public Object getSystemService(String name) {
@@ -105,17 +112,13 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
-                .thenReturn(new String[0]);
-        when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
-                .thenReturn(new String[0]);
-        when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
+        when(mResources.getStringArray(config_tether_dhcp_range)).thenReturn(new String[0]);
+        when(mResources.getStringArray(config_tether_usb_regexs)).thenReturn(new String[0]);
+        when(mResources.getStringArray(config_tether_wifi_regexs))
                 .thenReturn(new String[]{ "test_wlan\\d" });
-        when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
-                .thenReturn(new String[0]);
+        when(mResources.getStringArray(config_tether_bluetooth_regexs)).thenReturn(new String[0]);
         when(mResources.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
-        when(mResources.getStringArray(
-                com.android.internal.R.array.config_mobile_hotspot_provision_app))
+        when(mResources.getStringArray(config_mobile_hotspot_provision_app))
                 .thenReturn(new String[0]);
         mContentResolver = new MockContentResolver();
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
@@ -297,19 +300,16 @@
 
     private void setUpResourceForSubId() {
         when(mResourcesForSubId.getStringArray(
-                com.android.internal.R.array.config_tether_dhcp_range)).thenReturn(new String[0]);
+                config_tether_dhcp_range)).thenReturn(new String[0]);
         when(mResourcesForSubId.getStringArray(
-                com.android.internal.R.array.config_tether_usb_regexs)).thenReturn(new String[0]);
+                config_tether_usb_regexs)).thenReturn(new String[0]);
         when(mResourcesForSubId.getStringArray(
-                com.android.internal.R.array.config_tether_wifi_regexs))
-                .thenReturn(new String[]{ "test_wlan\\d" });
+                config_tether_wifi_regexs)).thenReturn(new String[]{ "test_wlan\\d" });
         when(mResourcesForSubId.getStringArray(
-                com.android.internal.R.array.config_tether_bluetooth_regexs))
-                .thenReturn(new String[0]);
+                config_tether_bluetooth_regexs)).thenReturn(new String[0]);
         when(mResourcesForSubId.getIntArray(config_tether_upstream_types)).thenReturn(new int[0]);
         when(mResourcesForSubId.getStringArray(
-                com.android.internal.R.array.config_mobile_hotspot_provision_app))
-                .thenReturn(PROVISIONING_APP_NAME);
+                config_mobile_hotspot_provision_app)).thenReturn(PROVISIONING_APP_NAME);
     }
 
 }
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 5d6d1c9..5712566 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -253,6 +253,8 @@
     NOTE_NETWORK_LOGGED_IN = 744;
     // A partial connectivity network was detected during network validation
     NOTE_NETWORK_PARTIAL_CONNECTIVITY = 745;
+    // Private DNS is broken in strict mode
+    NOTE_NETWORK_PRIVATE_DNS_BROKEN = 746;
 
     // Notify the user that their work profile has been deleted
     // Package: android
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e909e7a..68e11df32 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -366,9 +366,11 @@
                     if (userId != mCurrentUserId) {
                         return;
                     }
-                    AccessibilityUserState userState = getUserStateLocked(userId);
-                    boolean reboundAService = userState.getBindingServicesLocked().removeIf(
+                    final AccessibilityUserState userState = getUserStateLocked(userId);
+                    final boolean reboundAService = userState.getBindingServicesLocked().removeIf(
                             component -> component != null
+                                    && component.getPackageName().equals(packageName))
+                            || userState.mCrashedServices.removeIf(component -> component != null
                                     && component.getPackageName().equals(packageName));
                     if (reboundAService) {
                         onUserStateChangedLocked(userState);
@@ -393,6 +395,7 @@
                         if (compPkg.equals(packageName)) {
                             it.remove();
                             userState.getBindingServicesLocked().remove(comp);
+                            userState.getCrashedServicesLocked().remove(comp);
                             // Update the enabled services setting.
                             persistComponentNamesToSettingLocked(
                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
@@ -753,6 +756,7 @@
             userState.mEnabledServices.clear();
             userState.mEnabledServices.add(service);
             userState.getBindingServicesLocked().clear();
+            userState.getCrashedServicesLocked().clear();
             userState.mTouchExplorationGrantedServices.clear();
             userState.mTouchExplorationGrantedServices.add(service);
 
@@ -1178,6 +1182,10 @@
             AccessibilityServiceInfo accessibilityServiceInfo;
             try {
                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
+                if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) {
+                    // Restore the crashed attribute.
+                    accessibilityServiceInfo.crashed = true;
+                }
                 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
             } catch (XmlPullParserException | IOException xppe) {
                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
@@ -1418,8 +1426,9 @@
                 continue;
             }
 
-            // Wait for the binding if it is in process.
-            if (userState.getBindingServicesLocked().contains(componentName)) {
+            // Skip the component since it may be in process or crashed.
+            if (userState.getBindingServicesLocked().contains(componentName)
+                    || userState.getCrashedServicesLocked().contains(componentName)) {
                 continue;
             }
             if (userState.mEnabledServices.contains(componentName)
@@ -2687,6 +2696,7 @@
                     }
                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
                     if (readEnabledAccessibilityServicesLocked(userState)) {
+                        userState.updateCrashedServicesIfNeededLocked();
                         onUserStateChangedLocked(userState);
                     }
                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index d154060..a0a755a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -62,9 +62,6 @@
 
     private final Handler mMainHandler;
 
-    private boolean mWasConnectedAndDied;
-
-
     AccessibilityServiceConnection(AccessibilityUserState userState, Context context,
             ComponentName componentName,
             AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
@@ -168,8 +165,6 @@
 
     @Override
     public AccessibilityServiceInfo getServiceInfo() {
-        // Update crashed data
-        mAccessibilityServiceInfo.crashed = mWasConnectedAndDied;
         return mAccessibilityServiceInfo;
     }
 
@@ -178,10 +173,13 @@
         synchronized (mLock) {
             AccessibilityUserState userState = mUserStateWeakReference.get();
             if (userState == null) return;
-            Set<ComponentName> bindingServices = userState.getBindingServicesLocked();
-            if (bindingServices.contains(mComponentName) || mWasConnectedAndDied) {
+            final Set<ComponentName> bindingServices = userState.getBindingServicesLocked();
+            final Set<ComponentName> crashedServices = userState.getCrashedServicesLocked();
+            if (bindingServices.contains(mComponentName)
+                    || crashedServices.contains(mComponentName)) {
                 bindingServices.remove(mComponentName);
-                mWasConnectedAndDied = false;
+                crashedServices.remove(mComponentName);
+                mAccessibilityServiceInfo.crashed = false;
                 serviceInterface = mServiceInterface;
             }
             // There's a chance that service is removed from enabled_accessibility_services setting
@@ -271,7 +269,7 @@
             if (!isConnectedLocked()) {
                 return;
             }
-            mWasConnectedAndDied = true;
+            mAccessibilityServiceInfo.crashed = true;
             AccessibilityUserState userState = mUserStateWeakReference.get();
             if (userState != null) {
                 userState.serviceDisconnectedLocked(this);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 69f1e0e..a0b9866 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -73,6 +73,8 @@
 
     final Set<ComponentName> mBindingServices = new HashSet<>();
 
+    final Set<ComponentName> mCrashedServices = new HashSet<>();
+
     final Set<ComponentName> mEnabledServices = new HashSet<>();
 
     final Set<ComponentName> mTouchExplorationGrantedServices = new HashSet<>();
@@ -127,6 +129,7 @@
         // Clear service management state.
         mBoundServices.clear();
         mBindingServices.clear();
+        mCrashedServices.clear();
 
         // Clear event management state.
         mLastSentClientState = -1;
@@ -184,15 +187,16 @@
 
     /**
      * Make sure a services disconnected but still 'on' state is reflected in AccessibilityUserState
-     * There are three states to a service here: off, bound, and binding.
-     * This drops a service from a bound state, to the binding state.
-     * The binding state describes the situation where a service is on, but not bound.
+     * There are four states to a service here: off, bound, and binding, and crashed.
+     * This drops a service from a bound state, to the crashed state.
+     * The crashed state describes the situation where a service used to be bound, but no longer is
+     * despite still being enabled.
      *
      * @param serviceConnection The service.
      */
     void serviceDisconnectedLocked(AccessibilityServiceConnection serviceConnection) {
         removeServiceLocked(serviceConnection);
-        mBindingServices.add(serviceConnection.getComponentName());
+        mCrashedServices.add(serviceConnection.getComponentName());
     }
 
     /**
@@ -289,17 +293,44 @@
         mBindInstantServiceAllowed = allowed;
     }
 
+    /**
+     * Returns binding service list.
+     */
     Set<ComponentName> getBindingServicesLocked() {
         return mBindingServices;
     }
 
     /**
+     * Returns crashed service list.
+     */
+    Set<ComponentName> getCrashedServicesLocked() {
+        return mCrashedServices;
+    }
+
+    /**
      * Returns enabled service list.
      */
     Set<ComponentName> getEnabledServicesLocked() {
         return mEnabledServices;
     }
 
+    /**
+     * Remove service from crashed service list if users disable it.
+     */
+    void updateCrashedServicesIfNeededLocked() {
+        for (int i = 0, count = mInstalledServices.size(); i < count; i++) {
+            final AccessibilityServiceInfo installedService = mInstalledServices.get(i);
+            final ComponentName componentName = ComponentName.unflattenFromString(
+                    installedService.getId());
+
+            if (mCrashedServices.contains(componentName)
+                    && !mEnabledServices.contains(componentName)) {
+                // Remove it from mCrashedServices since users toggle the switch bar to retry.
+                mCrashedServices.remove(componentName);
+            }
+        }
+    }
+
     List<AccessibilityServiceConnection> getBoundServicesLocked() {
         return mBoundServices;
     }
@@ -439,6 +470,18 @@
                 pw.append(componentName.toShortString());
             }
         }
+        pw.println("}");
+        pw.append("     Crashed services:{");
+        it = mCrashedServices.iterator();
+        if (it.hasNext()) {
+            ComponentName componentName = it.next();
+            pw.append(componentName.toShortString());
+            while (it.hasNext()) {
+                componentName = it.next();
+                pw.append(", ");
+                pw.append(componentName.toShortString());
+            }
+        }
         pw.println("}]");
     }
 
diff --git a/services/art-profile b/services/art-profile
index cbc4627..a0338d5 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -20824,3 +20824,532 @@
 Lcom/google/android/startop/iorap/IorapForwardingService$AppLaunchObserver;
 Lcom/google/android/startop/iorap/IorapForwardingService$BinderConnectionHandler;
 Lcom/google/android/startop/iorap/IorapForwardingService;
+HPLandroid/hardware/health/V1_0/HealthInfo;-><init>()V
+HPLandroid/hardware/health/V2_0/DiskStats;-><init>()V
+HPLcom/android/server/-$$Lambda$GnssManagerService$a17GVVAgEci0VYD4EMvKwuPLhdQ;->onUidImportance(II)V
+HPLcom/android/server/-$$Lambda$GnssManagerService$mZAgy7PA5q3tB1aq7tHsX4xM14E;->run()V
+HPLcom/android/server/-$$Lambda$LocationManagerService$GVLGDgL1Vk3AKo-zMjRmo3-OLpQ;->run()V
+HPLcom/android/server/-$$Lambda$LocationManagerService$tHPgS5c0niUhGntiX8gOnWrZpg8;->onUidImportance(II)V
+HPLcom/android/server/accessibility/AccessibilityManagerService$Client;-><init>(Lcom/android/server/accessibility/AccessibilityManagerService;Landroid/view/accessibility/IAccessibilityManagerClient;ILcom/android/server/accessibility/AccessibilityUserState;)V
+HPLcom/android/server/accessibility/AccessibilitySecurityPolicy;->resolveCallingUserIdEnforcingPermissionsLocked(I)I
+HPLcom/android/server/am/-$$Lambda$OomAdjuster$OVkqAAacT5-taN3pgDzyZj3Ymvk;->handleMessage(Landroid/os/Message;)Z
+HPLcom/android/server/am/-$$Lambda$ProcessList$vtq7LF5jIHO4t5NE03c8g7BT7Jc;->run()V
+HPLcom/android/server/am/ActivityManagerService$2;->onActivityLaunched([BI)V
+HPLcom/android/server/am/ActivityManagerService$4;->isPackageForFilter(Ljava/lang/String;Landroid/content/IntentFilter;)Z
+HPLcom/android/server/am/ActivityManagerService$4;->newResult(Landroid/content/IntentFilter;II)Ljava/lang/Object;
+HPLcom/android/server/am/ActivityManagerService$PidMap;->put(Lcom/android/server/am/ProcessRecord;)V
+HPLcom/android/server/am/ActivityManagerService;->trimApplications(Ljava/lang/String;)V
+HPLcom/android/server/am/ActivityManagerService;->updateOomAdjLocked(Lcom/android/server/am/ProcessRecord;Ljava/lang/String;)V
+HPLcom/android/server/am/ActivityManagerService;->updateOomAdjLocked(Lcom/android/server/am/ProcessRecord;ZLjava/lang/String;)Z
+HPLcom/android/server/am/HostingRecord;->getName()Ljava/lang/String;
+HPLcom/android/server/am/HostingRecord;->getType()Ljava/lang/String;
+HPLcom/android/server/am/OomAdjuster;->setAttachingSchedGroupLocked(Lcom/android/server/am/ProcessRecord;)V
+HPLcom/android/server/am/ProcessList;->startProcessLocked(Lcom/android/server/am/HostingRecord;Ljava/lang/String;Lcom/android/server/am/ProcessRecord;I[IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)Z
+HPLcom/android/server/am/ProcessRecord;->computeOomAdjFromActivitiesIfNecessary(Lcom/android/server/am/OomAdjuster$ComputeOomAdjWindowCallback;IZIIIII)V
+HPLcom/android/server/appop/AppOpsService$FeatureOp;->started(JII)V
+HPLcom/android/server/appop/AppOpsService$FeatureOp;->updateProxyState(JILjava/lang/String;Ljava/lang/String;)V
+HPLcom/android/server/appop/AppOpsService;->noteOperation(IILjava/lang/String;Ljava/lang/String;)I
+HPLcom/android/server/appop/AudioRestrictionManager;->checkAudioOperation(IIILjava/lang/String;)I
+HPLcom/android/server/appprediction/-$$Lambda$AppPredictionManagerService$PredictionManagerServiceStub$4yDhFef-19aMlJ-Y7O6RdjSAvnk;-><init>(Landroid/app/prediction/AppPredictionSessionId;Landroid/app/prediction/AppTargetEvent;)V
+HPLcom/android/server/appprediction/-$$Lambda$RemoteAppPredictionService$qroIh2ewx0BLP-J9XIAX2CaX8J4;-><init>(Landroid/app/prediction/AppPredictionSessionId;Landroid/app/prediction/AppTargetEvent;)V
+HPLcom/android/server/appprediction/AppPredictionManagerService$PredictionManagerServiceStub;->runForUserLocked(Ljava/lang/String;Ljava/util/function/Consumer;)V
+HPLcom/android/server/appprediction/RemoteAppPredictionService;->lambda$notifyAppTargetEvent$1(Landroid/app/prediction/AppPredictionSessionId;Landroid/app/prediction/AppTargetEvent;Landroid/service/appprediction/IPredictionService;)V
+HPLcom/android/server/audio/SoundEffectsHelper$SfxHandler;->handleMessage(Landroid/os/Message;)V
+HPLcom/android/server/autofill/AutofillManagerService$AugmentedAutofillState;->injectAugmentedAutofillInfo(Landroid/content/AutofillOptions;ILjava/lang/String;)V
+HPLcom/android/server/autofill/AutofillManagerService$LocalService;->injectDisableAppInfo(Landroid/content/AutofillOptions;ILjava/lang/String;)V
+HPLcom/android/server/compat/CompatConfig;->getDisabledChanges(Landroid/content/pm/ApplicationInfo;)[J
+HPLcom/android/server/compat/CompatConfig;->get()Lcom/android/server/compat/CompatConfig;
+HPLcom/android/server/compat/PlatformCompat;->resetReporting(Landroid/content/pm/ApplicationInfo;)V
+HPLcom/android/server/contentcapture/ContentCaptureManagerService$GlobalContentCaptureOptions;->getOptions(ILjava/lang/String;)Landroid/content/ContentCaptureOptions;
+HPLcom/android/server/input/InputManagerService;->onPointerDownOutsideFocus(Landroid/os/IBinder;)V
+HPLcom/android/server/input/InputManagerService;->registerInputChannel(Landroid/view/InputChannel;)V
+HPLcom/android/server/inputmethod/InputMethodManagerService;->getActivityViewToScreenMatrixLocked(II)Landroid/graphics/Matrix;
+HPLcom/android/server/media/projection/MediaProjectionManagerService$1;->onForegroundActivitiesChanged(IIZ)V
+HPLcom/android/server/net/NetworkPolicyManagerService;->updateRulesForPowerRestrictionsULInner(II)I
+HPLcom/android/server/pm/permission/PermissionManagerService;->checkSingleUidPermissionInternal(ILjava/lang/String;)Z
+HPLcom/android/server/policy/PermissionPolicyService$Internal;->checkStartActivity(Landroid/content/Intent;ILjava/lang/String;)Z
+HPLcom/android/server/soundtrigger/SoundTriggerHelper;->computeRecognitionRequestedLocked()Z
+HPLcom/android/server/soundtrigger/SoundTriggerHelper;->isRecognitionAllowed()Z
+HPLcom/android/server/statusbar/-$$Lambda$StatusBarManagerService$dQguzfF4tEgBOj3Pr8MpGRN8HT0;->run()V
+HPLcom/android/server/statusbar/-$$Lambda$StatusBarManagerService$u5u_W7qW5cMnzk9Qhp_oReST4Dc;->run()V
+HPLcom/android/server/statusbar/StatusBarManagerService;->setImeWindowStatus(ILandroid/os/IBinder;IIZZ)V
+HPLcom/android/server/usage/UsageStatsService;->reportEventOrAddToQueue(ILandroid/app/usage/UsageEvents$Event;)V
+HPLcom/android/server/usage/UserUsageStatsService;->checkAndGetTimeLocked()J
+HPLcom/android/server/wm/-$$Lambda$1Hjf_Nn5x4aIy9rIBTwVrtrzWFA;->apply(Ljava/lang/Object;)Ljava/lang/Object;
+HPLcom/android/server/wm/-$$Lambda$9vBfnQOmNnsc9WU80IIatZHQGKc;->get()Ljava/lang/Object;
+HPLcom/android/server/wm/-$$Lambda$ActivityRecord$BGON-BKR54yaxY8PHFXNV2xpxCM;->accept(Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$ActivityRecord$tt99EJHW_Nk5qgU9galJBIm5wXg;->run()V
+HPLcom/android/server/wm/-$$Lambda$ActivityRecord$YSVwd546vKWMiMYy7MFzg1qRiio;-><init>(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/-$$Lambda$ActivityRecord$YY5kCNb4uWg5W_2lbH3ZOqirP1g;->apply(Ljava/lang/Object;)Z
+HPLcom/android/server/wm/-$$Lambda$DisplayContent$a4EkCBfpZNIl1xfYgm2ktgndF8w;->apply(Ljava/lang/Object;)Z
+HPLcom/android/server/wm/-$$Lambda$DisplayContent$D0QJUvhaQkGgoMtOmjw5foY9F8M;->accept(Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayContent$eJsj3GR1HdCnOJrZ8_oaLP52jg0;->accept(Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayContent$SeHNTr4WUVpGmQniHULUi1ST7k8;->accept(Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayContent$sYPOy6TL-QiWuU_jcEHYn4HeFnQ;->accept(Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$3MnyIKSHFLqhfUifWEQPNp_-J6A;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$IOyP8YVRG92tn9u1muYWZgBbgc0;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$J8sIwXJvltUaPM3jEGO948Bx9ig;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$LkHee4mchNXMwNt7HLgsMzHofeE;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$QDPgWUhyEOraWnf6a-u4mTBttdw;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$qQY9m_Itua9TDy-Nk3zzDxvjEwE;->run()V
+HPLcom/android/server/wm/-$$Lambda$LaunchObserverRegistryImpl$QcawcFcJtEX4EhYptq_Vb4j368Y;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$LaunchObserverRegistryImpl$veRn_GhgLZLlOHOJ0ZYT6KcfYqo;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$qMFJUmfG50ZSjk7Tac67xBia0d4;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$RemoteAnimationController$74uuXaM2TqjkzYi0b8LqJdbycxA;-><init>(Lcom/android/server/wm/RemoteAnimationController;[Landroid/view/RemoteAnimationTarget;[Landroid/view/RemoteAnimationTarget;)V
+HPLcom/android/server/wm/-$$Lambda$RemoteAnimationController$74uuXaM2TqjkzYi0b8LqJdbycxA;->run()V
+HPLcom/android/server/wm/-$$Lambda$RootWindowContainer$7XcqfZjQLAbjpIyed3iDnVtZro4;->accept(Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$SurfaceAnimator$M9kRDTUpVS03LTqe-QLQz3DnMhk;-><init>(Lcom/android/server/wm/SurfaceAnimator;Lcom/android/server/wm/AnimationAdapter;Ljava/lang/Runnable;)V
+HPLcom/android/server/wm/-$$Lambda$SurfaceAnimator$M9kRDTUpVS03LTqe-QLQz3DnMhk;->run()V
+HPLcom/android/server/wm/-$$Lambda$TaskChangeNotificationController$Kz-Od_gLhLbMtGka4r78W0Gmzgo;->accept(Landroid/app/ITaskStackListener;Landroid/os/Message;)V
+HPLcom/android/server/wm/-$$Lambda$TaskPersister$xdLXwftXa6l84QTg1zpxMnmtQ0g;-><init>(Lcom/android/server/wm/TaskRecord;)V
+HPLcom/android/server/wm/-$$Lambda$uwO6wQlqU3CG7OTdH7NBCKnHs64;->accept(Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$UZl9uqUNteVgplGGEK6TMzf-7zk;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$VY87MmFWaCLMkNa2qHGaPrThyrI;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/ActivityDisplay;->alwaysCreateStack(II)Z
+HPLcom/android/server/wm/ActivityDisplay;->pauseBackStacks(ZLcom/android/server/wm/ActivityRecord;)Z
+HPLcom/android/server/wm/ActivityDisplay;->updateDisplayOverrideConfigurationLocked(Landroid/content/res/Configuration;Lcom/android/server/wm/ActivityRecord;ZLcom/android/server/wm/ActivityTaskManagerService$UpdateConfigurationResult;)Z
+HPLcom/android/server/wm/ActivityMetricsLogger;->reset(ZLcom/android/server/wm/ActivityMetricsLogger$WindowingModeTransitionInfo;Ljava/lang/String;J)V
+HPLcom/android/server/wm/ActivityRecord$AddStartingWindow;-><init>(Lcom/android/server/wm/ActivityRecord;Lcom/android/server/wm/ActivityRecord$1;)V
+HPLcom/android/server/wm/ActivityRecord$AddStartingWindow;->run()V
+HPLcom/android/server/wm/ActivityRecord$Token;-><init>(Landroid/content/Intent;)V
+HPLcom/android/server/wm/ActivityRecord;->addWindow(Lcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/ActivityRecord;->adjustPinnedStackAndInitChangeTransitionIfNeeded(II)V
+HPLcom/android/server/wm/ActivityRecord;->asActivityRecord()Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/ActivityRecord;->checkAppWindowsReadyToShow()V
+HPLcom/android/server/wm/ActivityRecord;->checkCompleteDeferredRemoval()Z
+HPLcom/android/server/wm/ActivityRecord;->clearAnimatingFlags()V
+HPLcom/android/server/wm/ActivityRecord;->commitVisibility(Landroid/view/WindowManager$LayoutParams;ZIZZ)Z
+HPLcom/android/server/wm/ActivityRecord;->computeBounds(Landroid/graphics/Rect;Landroid/graphics/Rect;)V
+HPLcom/android/server/wm/ActivityRecord;->containsDismissKeyguardWindow()Z
+HPLcom/android/server/wm/ActivityRecord;->containsShowWhenLockedWindow()Z
+HPLcom/android/server/wm/ActivityRecord;->destroySurfaces(Z)V
+HPLcom/android/server/wm/ActivityRecord;->detachChildren()V
+HPLcom/android/server/wm/ActivityRecord;->fillsParent()Z
+HPLcom/android/server/wm/ActivityRecord;->findMainWindow()Lcom/android/server/wm/WindowState;
+HPLcom/android/server/wm/ActivityRecord;->findMainWindow(Z)Lcom/android/server/wm/WindowState;
+HPLcom/android/server/wm/ActivityRecord;->forAllWindows(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+HPLcom/android/server/wm/ActivityRecord;->getAnimationLeashParent()Landroid/view/SurfaceControl;
+HPLcom/android/server/wm/ActivityRecord;->getDisplayedBounds()Landroid/graphics/Rect;
+HPLcom/android/server/wm/ActivityRecord;->getOrientation(I)I
+HPLcom/android/server/wm/ActivityRecord;->getStartingWindowType(ZZZZZZLandroid/app/ActivityManager$TaskSnapshot;)I
+HPLcom/android/server/wm/ActivityRecord;->getTask()Lcom/android/server/wm/Task;
+HPLcom/android/server/wm/ActivityRecord;->handleAlreadyVisible()V
+HPLcom/android/server/wm/ActivityRecord;->isAppAnimating()Z
+HPLcom/android/server/wm/ActivityRecord;->isClientHidden()Z
+HPLcom/android/server/wm/ActivityRecord;->isFirstChildWindowGreaterThanSecond(Lcom/android/server/wm/WindowState;Lcom/android/server/wm/WindowState;)Z
+HPLcom/android/server/wm/ActivityRecord;->isResolverOrDelegateActivity()Z
+HPLcom/android/server/wm/ActivityRecord;->isSelfAnimating()Z
+HPLcom/android/server/wm/ActivityRecord;->isVisible()Z
+HPLcom/android/server/wm/ActivityRecord;->isWaitingForTransitionStart()Z
+HPLcom/android/server/wm/ActivityRecord;->layoutLetterbox(Lcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/ActivityRecord;->makeInvisible()V
+HPLcom/android/server/wm/ActivityRecord;->needsZBoost()Z
+HPLcom/android/server/wm/ActivityRecord;->onAnimationLeashCreated(Landroid/view/SurfaceControl$Transaction;Landroid/view/SurfaceControl;)V
+HPLcom/android/server/wm/ActivityRecord;->onAnimationLeashLost(Landroid/view/SurfaceControl$Transaction;)V
+HPLcom/android/server/wm/ActivityRecord;->onAppTransitionDone()V
+HPLcom/android/server/wm/ActivityRecord;->onDisplayChanged(Lcom/android/server/wm/DisplayContent;)V
+HPLcom/android/server/wm/ActivityRecord;->onParentChanged()V
+HPLcom/android/server/wm/ActivityRecord;->postWindowRemoveStartingWindowCleanup(Lcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/ActivityRecord;->prepareSurfaces()V
+HPLcom/android/server/wm/ActivityRecord;->removeChild(Lcom/android/server/wm/WindowContainer;)V
+HPLcom/android/server/wm/ActivityRecord;->removeStartingWindow()V
+HPLcom/android/server/wm/ActivityRecord;->scheduleAddStartingWindow()V
+HPLcom/android/server/wm/ActivityRecord;->scheduleTopResumedActivityChanged(Z)Z
+HPLcom/android/server/wm/ActivityRecord;->setHidden(Z)V
+HPLcom/android/server/wm/ActivityRecord;->setLayer(Landroid/view/SurfaceControl$Transaction;I)V
+HPLcom/android/server/wm/ActivityRecord;->setVisibility(ZZ)V
+HPLcom/android/server/wm/ActivityRecord;->shouldDeferAnimationFinish(Ljava/lang/Runnable;)Z
+HPLcom/android/server/wm/ActivityRecord;->stopFreezingScreen(ZZ)V
+HPLcom/android/server/wm/ActivityRecord;->stopIfPossible()V
+HPLcom/android/server/wm/ActivityRecord;->transferStartingWindow(Landroid/os/IBinder;)Z
+HPLcom/android/server/wm/ActivityRecord;->updateAllDrawn()V
+HPLcom/android/server/wm/ActivityRecord;->updateDrawnWindowStates(Lcom/android/server/wm/WindowState;)Z
+HPLcom/android/server/wm/ActivityRecord;->updateLetterboxSurface(Lcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/ActivityRecord;->updateReportedVisibilityLocked()V
+HPLcom/android/server/wm/ActivityRecord;->windowsAreFocusable()Z
+HPLcom/android/server/wm/ActivityRecord;->writeToProto(Landroid/util/proto/ProtoOutputStream;JI)V
+HPLcom/android/server/wm/ActivityStack;->removeLaunchTickMessages()V
+HPLcom/android/server/wm/ActivityStack;->removeStopTimeoutForActivity(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/ActivityStack;->scheduleLaunchTickForActivity(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/ActivityStack;->topTask()Lcom/android/server/wm/TaskRecord;
+HPLcom/android/server/wm/ActivityStarter;->startActivity(Lcom/android/server/wm/ActivityRecord;Lcom/android/server/wm/ActivityRecord;Landroid/service/voice/IVoiceInteractionSession;Lcom/android/internal/app/IVoiceInteractor;IZLandroid/app/ActivityOptions;Lcom/android/server/wm/TaskRecord;[Lcom/android/server/wm/ActivityRecord;Z)I
+HPLcom/android/server/wm/ActivityTaskManagerService;->addWindowLayoutReasons(I)V
+HPLcom/android/server/wm/ActivityTaskManagerService;->continueWindowLayout()V
+HPLcom/android/server/wm/ActivityTaskManagerService;->deferWindowLayout()V
+HPLcom/android/server/wm/ActivityTaskManagerService;->getPermissionPolicyInternal()Lcom/android/server/policy/PermissionPolicyInternal;
+HPLcom/android/server/wm/ActivityTaskManagerService;->isCrossUserAllowed(II)Z
+HPLcom/android/server/wm/ActivityTaskManagerService;->startProcessAsync(Lcom/android/server/wm/ActivityRecord;ZZLjava/lang/String;)V
+HPLcom/android/server/wm/AppTransitionController;->findAnimLayoutParamsToken(ILandroid/util/ArraySet;)Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/AppTransitionController;->getRemoteAnimationOverride(Lcom/android/server/wm/ActivityRecord;ILandroid/util/ArraySet;)Landroid/view/RemoteAnimationAdapter;
+HPLcom/android/server/wm/AppTransitionController;->getTopApp(Landroid/util/ArraySet;Z)Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/AppTransition;->getAnimationStyleResId(Landroid/view/WindowManager$LayoutParams;)I
+HPLcom/android/server/wm/AppTransition;->goodToGo(ILcom/android/server/wm/ActivityRecord;Landroid/util/ArraySet;)I
+HPLcom/android/server/wm/AppTransition;->setLastAppTransition(ILcom/android/server/wm/ActivityRecord;Lcom/android/server/wm/ActivityRecord;Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/ConfigurationContainer;->hasChild()Z
+HPLcom/android/server/wm/ConfigurationContainer;->setWindowingMode(I)V
+HPLcom/android/server/wm/DisplayContent;->computeImeTargetIfNeeded(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/DisplayContent;->getInsetsPolicy()Lcom/android/server/wm/InsetsPolicy;
+HPLcom/android/server/wm/DisplayContent;->getRotationAnimation()Lcom/android/server/wm/ScreenRotationAnimation;
+HPLcom/android/server/wm/DisplayContent;->performLayoutNoTrace(ZZ)V
+HPLcom/android/server/wm/DisplayContent;->setFocusedApp(Lcom/android/server/wm/ActivityRecord;)Z
+HPLcom/android/server/wm/DisplayContent;->updateDisplayAndOrientation(ILandroid/content/res/Configuration;)Landroid/view/DisplayInfo;
+HPLcom/android/server/wm/DisplayContent;->updateFocusedWindowLocked(IZI)Z
+HPLcom/android/server/wm/DisplayContent;->updateOrientation(Landroid/content/res/Configuration;Landroid/os/IBinder;Z)Landroid/content/res/Configuration;
+HPLcom/android/server/wm/DisplayContent;->updateOrientation()Z
+HPLcom/android/server/wm/DisplayPolicy;->addWindowLw(Lcom/android/server/wm/WindowState;Landroid/view/WindowManager$LayoutParams;)V
+HPLcom/android/server/wm/DisplayPolicy;->adjustWindowParamsLw(Lcom/android/server/wm/WindowState;Landroid/view/WindowManager$LayoutParams;II)V
+HPLcom/android/server/wm/DisplayPolicy;->configureNavBarOpacity(IZZZZZ)I
+HPLcom/android/server/wm/DisplayPolicy;->drawsBarBackground(ILcom/android/server/wm/WindowState;Lcom/android/server/wm/BarController;I)Z
+HPLcom/android/server/wm/DisplayPolicy;->drawsNavigationBarBackground(ILcom/android/server/wm/WindowState;)Z
+HPLcom/android/server/wm/DisplayPolicy;->getRefreshRatePolicy()Lcom/android/server/wm/RefreshRatePolicy;
+HPLcom/android/server/wm/DisplayPolicy;->isWindowExcludedFromContent(Lcom/android/server/wm/WindowState;)Z
+HPLcom/android/server/wm/DisplayPolicy;->selectAnimation(Lcom/android/server/wm/WindowState;I)I
+HPLcom/android/server/wm/DisplayPolicy;->updateConfigurationAndScreenSizeDependentBehaviors()V
+HPLcom/android/server/wm/DisplayRotation;->getRotation()I
+HPLcom/android/server/wm/DisplayRotation;->markForSeamlessRotation(Lcom/android/server/wm/WindowState;Z)V
+HPLcom/android/server/wm/ImeInsetsSourceProvider;->onPostInsetsDispatched()V
+HPLcom/android/server/wm/ImeInsetsSourceProvider;->onPostLayout()V
+HPLcom/android/server/wm/InputManagerCallback;->notifyFocusChanged(Landroid/os/IBinder;Landroid/os/IBinder;)Z
+HPLcom/android/server/wm/InputMonitor$UpdateInputWindows;->run()V
+HPLcom/android/server/wm/InsetsPolicy;->areSystemBarsForciblyVisible()Z
+HPLcom/android/server/wm/InsetsPolicy;->isNavBarForciblyVisible()Z
+HPLcom/android/server/wm/InsetsPolicy;->isStatusBarForciblyVisible()Z
+HPLcom/android/server/wm/InsetsStateController;->getImeSourceProvider()Lcom/android/server/wm/ImeInsetsSourceProvider;
+HPLcom/android/server/wm/InsetsStateController;->onBarControlTargetChanged(Lcom/android/server/wm/InsetsControlTarget;Lcom/android/server/wm/InsetsControlTarget;)V
+HPLcom/android/server/wm/LaunchObserverRegistryImpl;->onIntentStarted(Landroid/content/Intent;J)V
+HPLcom/android/server/wm/PinnedStackController;->resetReentrySnapFraction(Landroid/content/ComponentName;)V
+HPLcom/android/server/wm/RecentTasks;->isInVisibleRange(Lcom/android/server/wm/TaskRecord;IIZ)Z
+HPLcom/android/server/wm/RefreshRatePolicy;->getPreferredModeId(Lcom/android/server/wm/WindowState;)I
+HPLcom/android/server/wm/RemoteAnimationController$FinishedCallback;-><init>(Lcom/android/server/wm/RemoteAnimationController;)V
+HPLcom/android/server/wm/RemoteAnimationController$RemoteAnimationRecord;->getMode()I
+HPLcom/android/server/wm/RemoteAnimationController;->createAppAnimations()[Landroid/view/RemoteAnimationTarget;
+HPLcom/android/server/wm/RemoteAnimationController;->createWallpaperAnimations()[Landroid/view/RemoteAnimationTarget;
+HPLcom/android/server/wm/RemoteAnimationController;-><init>(Lcom/android/server/wm/WindowManagerService;Landroid/view/RemoteAnimationAdapter;Landroid/os/Handler;)V
+HPLcom/android/server/wm/RemoteAnimationController;->releaseFinishedCallback()V
+HPLcom/android/server/wm/RemoteAnimationController;->setRunningRemoteAnimation(Z)V
+HPLcom/android/server/wm/RemoteAnimationController;->unlinkToDeathOfRunner()V
+HPLcom/android/server/wm/RootActivityContainer;->getLaunchStack(Lcom/android/server/wm/ActivityRecord;Landroid/app/ActivityOptions;Lcom/android/server/wm/TaskRecord;ZLcom/android/server/wm/LaunchParamsController$LaunchParams;II)Lcom/android/server/wm/ActivityStack;
+HPLcom/android/server/wm/RootActivityContainer;->getRunningTasks(ILjava/util/List;IIIZZLandroid/util/ArraySet;)V
+HPLcom/android/server/wm/RootWindowContainer;->getActivityRecord(Landroid/os/IBinder;)Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/Session;->finishDrawing(Landroid/view/IWindow;Landroid/view/SurfaceControl$Transaction;)V
+HPLcom/android/server/wm/Session;->reportSystemGestureExclusionChanged(Landroid/view/IWindow;Ljava/util/List;)V
+HPLcom/android/server/wm/StartingData;-><init>(Lcom/android/server/wm/WindowManagerService;)V
+HPLcom/android/server/wm/SurfaceAnimationRunner;->startPendingAnimationsLocked()V
+HPLcom/android/server/wm/SurfaceAnimator$Animatable;->shouldDeferAnimationFinish(Ljava/lang/Runnable;)Z
+HPLcom/android/server/wm/SurfaceAnimator;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/android/server/wm/Task;->addChild(Lcom/android/server/wm/ActivityRecord;I)V
+HPLcom/android/server/wm/TaskChangeNotificationController;->notifyTaskListUpdated()V
+HPLcom/android/server/wm/Task;->getTopVisibleActivity()Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/TaskLaunchParamsModifier;->canInheritWindowingModeFromSource(Lcom/android/server/wm/ActivityDisplay;Lcom/android/server/wm/ActivityRecord;)Z
+HPLcom/android/server/wm/Task;->onConfigurationChanged(Landroid/content/res/Configuration;Z)V
+HPLcom/android/server/wm/TaskPersister$TaskWriteQueueItem;-><init>(Lcom/android/server/wm/TaskRecord;Lcom/android/server/wm/ActivityTaskManagerService;)V
+HPLcom/android/server/wm/Task;->positionChildAt(Lcom/android/server/wm/ActivityRecord;I)V
+HPLcom/android/server/wm/TaskRecord;->computeFullscreenBounds(Landroid/graphics/Rect;Lcom/android/server/wm/ActivityRecord;Landroid/graphics/Rect;I)V
+HPLcom/android/server/wm/TaskRecord;->findRootIndex(Z)I
+HPLcom/android/server/wm/TaskRecord;-><init>(Lcom/android/server/wm/ActivityTaskManagerService;ILandroid/content/pm/ActivityInfo;Landroid/content/Intent;Landroid/service/voice/IVoiceInteractionSession;Lcom/android/internal/app/IVoiceInteractor;Landroid/app/ActivityManager$TaskDescription;)V
+HPLcom/android/server/wm/UnknownAppVisibilityController;->notifyAppResumedFinished(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/UnknownAppVisibilityController;->notifyRelayouted(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->getLeashFinishedCallback()Lcom/android/server/wm/SurfaceAnimator$OnAnimationFinishedCallback;
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->lambda$startWallpaperAnimations$0(JJLjava/util/function/Consumer;Ljava/util/ArrayList;Ljava/util/ArrayList;Lcom/android/server/wm/WallpaperWindowToken;)V
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->startAnimation(Landroid/view/SurfaceControl;Landroid/view/SurfaceControl$Transaction;Lcom/android/server/wm/SurfaceAnimator$OnAnimationFinishedCallback;)V
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->startWallpaperAnimations(Lcom/android/server/wm/WindowManagerService;JJLjava/util/function/Consumer;Ljava/util/ArrayList;)[Landroid/view/RemoteAnimationTarget;
+HPLcom/android/server/wm/WindowAnimator;->cancelAnimation()V
+HPLcom/android/server/wm/WindowContainer;->onAnimationLeashLost(Landroid/view/SurfaceControl$Transaction;)V
+HPLcom/android/server/wm/WindowContainer;->onParentChanged(Lcom/android/server/wm/WindowContainer$PreAssignChildLayersCallback;)V
+HPLcom/android/server/wm/WindowManagerService$LocalService;->isStackVisibleLw(I)Z
+HPLcom/android/server/wm/WindowManagerService;->prepareNoneTransitionForRelaunching(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/WindowManagerService;->prepareWindowReplacementTransition(Lcom/android/server/wm/ActivityRecord;)Z
+HPLcom/android/server/wm/WindowProcessController;->createProfilerInfoIfNeeded()Landroid/app/ProfilerInfo;
+HPLcom/android/server/wm/WindowProcessControllerMap;->put(ILcom/android/server/wm/WindowProcessController;)V
+HPLcom/android/server/wm/WindowProcessController;->onStartActivity(ILandroid/content/pm/ActivityInfo;)V
+HPLcom/android/server/wm/WindowProcessController;->setLastActivityLaunchTime(J)V
+HPLcom/android/server/wm/WindowState$UpdateReportedVisibilityResults;-><init>()V
+HPLcom/android/server/wm/WindowState;->getLastReportedConfiguration()Landroid/content/res/Configuration;
+HPLcom/android/server/wm/WindowState;->getSurfaceTouchableRegion(Landroid/view/InputWindowHandle;I)I
+HPLcom/android/server/wm/WindowState;->logExclusionRestrictions(I)V
+HPLcom/android/server/wm/WindowState;->onAnimationLeashLost(Landroid/view/SurfaceControl$Transaction;)V
+HPLcom/android/server/wm/WindowState;->relayoutVisibleWindow(II)I
+HPLcom/android/server/wm/WindowState;->updateLocationInParentDisplayIfNeeded()V
+HPLcom/android/server/wm/WindowSurfaceController;-><init>(Ljava/lang/String;IIIILcom/android/server/wm/WindowStateAnimator;II)V
+HPLcom/android/server/wm/WindowSurfacePlacer$Traverser;->run()V
+HPLcom/android/server/wm/WindowToken;-><init>(Lcom/android/server/wm/WindowManagerService;Landroid/os/IBinder;IZLcom/android/server/wm/DisplayContent;Z)V
+HPLcom/google/android/startop/iorap/IorapForwardingService$AppLaunchObserver;->onActivityLaunched([BI)V
+HPLcom/android/server/accessibility/AccessibilityManagerService;->computeRelevantEventTypesLocked(Lcom/android/server/accessibility/AccessibilityUserState;Lcom/android/server/accessibility/AccessibilityManagerService$Client;)I
+HPLcom/android/server/accessibility/AccessibilitySecurityPolicy;->resolveProfileParentLocked(I)I
+HPLcom/android/server/am/-$$Lambda$ProcessList$vtq7LF5jIHO4t5NE03c8g7BT7Jc;-><init>(Lcom/android/server/am/ProcessList;Lcom/android/server/am/ProcessRecord;Ljava/lang/String;[IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V
+HPLcom/android/server/am/ActivityManagerService$2;->onActivityLaunchFinished([BJ)V
+HPLcom/android/server/am/ActivityManagerService$2;->onIntentStarted(Landroid/content/Intent;J)V
+HPLcom/android/server/am/ActivityManagerService$4;->isPackageForFilter(Ljava/lang/String;Lcom/android/server/am/BroadcastFilter;)Z
+HPLcom/android/server/am/ActivityManagerService$4;->newResult(Lcom/android/server/am/BroadcastFilter;II)Lcom/android/server/am/BroadcastFilter;
+HPLcom/android/server/am/ActivityManagerService$LocalService;->startProcess(Ljava/lang/String;Landroid/content/pm/ApplicationInfo;ZZLjava/lang/String;Landroid/content/ComponentName;)V
+HPLcom/android/server/am/ActivityManagerService;->trimApplicationsLocked(Ljava/lang/String;)V
+HPLcom/android/server/am/ProcessList;->lambda$startProcessLocked$0$ProcessList(Lcom/android/server/am/ProcessRecord;Ljava/lang/String;[IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V
+HPLcom/android/server/am/ProcessRecord;->onStartActivity(IZLjava/lang/String;J)V
+HPLcom/android/server/am/ProcessRecord;->setRunningRemoteAnimation(Z)V
+HPLcom/android/server/am/ProcessRecord;->setStartParams(ILcom/android/server/am/HostingRecord;Ljava/lang/String;J)V
+HPLcom/android/server/appprediction/RemoteAppPredictionService;->lambda$notifyAppTargetEvent$1(Landroid/app/prediction/AppPredictionSessionId;Landroid/app/prediction/AppTargetEvent;Landroid/service/appprediction/IPredictionService;)V
+HPLcom/android/server/audio/SoundEffectsHelper$SfxHandler$1;-><init>(Lcom/android/server/audio/SoundEffectsHelper$SfxHandler;Landroid/os/Message;)V
+HPLcom/android/server/audio/SoundEffectsHelper;->onLoadSoundEffects(Lcom/android/server/audio/SoundEffectsHelper$OnEffectsLoadCompleteHandler;)V
+HPLcom/android/server/autofill/AutofillManagerServiceImpl;->getAppDisabledActivitiesLocked(Ljava/lang/String;)Landroid/util/ArrayMap;
+HPLcom/android/server/compat/CompatChange;->isEnabled(Landroid/content/pm/ApplicationInfo;)Z
+HPLcom/android/server/GnssManagerService;->onForegroundChanged(IZ)V
+HPLcom/android/server/LocationManagerService;->lambda$initializeLocked$4$LocationManagerService(II)V
+HPLcom/android/server/LocationManagerService;->lambda$initializeLocked$5$LocationManagerService(II)V
+HPLcom/android/server/policy/PermissionPolicyService$Internal;->isActionRemovedForCallingPackage(Landroid/content/Intent;ILjava/lang/String;)Z
+HPLcom/android/server/statusbar/-$$Lambda$StatusBarManagerService$dQguzfF4tEgBOj3Pr8MpGRN8HT0;-><init>(Lcom/android/server/statusbar/StatusBarManagerService;ILandroid/os/IBinder;IIZZ)V
+HPLcom/android/server/statusbar/StatusBarManagerService;->lambda$setImeWindowStatus$2$StatusBarManagerService(ILandroid/os/IBinder;IIZZ)V
+HPLcom/android/server/statusbar/StatusBarManagerService;->lambda$updateUiVisibilityLocked$3$StatusBarManagerService(IIIIILandroid/graphics/Rect;Landroid/graphics/Rect;Z)V
+HPLcom/android/server/wm/-$$Lambda$ActivityRecord$tt99EJHW_Nk5qgU9galJBIm5wXg;-><init>(Lcom/android/server/policy/WindowManagerPolicy$StartingSurface;)V
+HPLcom/android/server/wm/-$$Lambda$RemoteAnimationController$dP8qDptNigoqhzVtIudsX5naGu4;-><init>(Lcom/android/server/wm/RemoteAnimationController;)V
+HPLcom/android/server/wm/-$$Lambda$RemoteAnimationController$uQS8vaPKQ-E3x_9G8NCxPQmw1fw;-><init>(Lcom/android/server/wm/RemoteAnimationController;)V
+HPLcom/android/server/wm/ActivityRecord;->addToStopping(ZZLjava/lang/String;)V
+HPLcom/android/server/wm/ActivityRecord;->allDrawnStatesConsidered()Z
+HPLcom/android/server/wm/ActivityRecord;->applyAnimationLocked(Landroid/view/WindowManager$LayoutParams;IZZ)Z
+HPLcom/android/server/wm/ActivityRecord;->checkKeyguardFlagsChanged()V
+HPLcom/android/server/wm/ActivityRecord;->lambda$removeStartingWindow$3(Lcom/android/server/policy/WindowManagerPolicy$StartingSurface;)V
+HPLcom/android/server/wm/ActivityRecord;->shouldStartChangeTransition(II)Z
+HPLcom/android/server/wm/ActivityRecord;->transferStartingWindowFromHiddenAboveTokenIfNeeded()V
+HPLcom/android/server/wm/ActivityStack;->scheduleStopTimeoutForActivity(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/ActivityStack;->startPausingLocked(ZZLcom/android/server/wm/ActivityRecord;)Z
+HPLcom/android/server/wm/ActivityStackSupervisor;->getRunningTasks()Lcom/android/server/wm/RunningTasks;
+HPLcom/android/server/wm/ActivityStackSupervisor;->getSystemChooserActivity()Landroid/content/ComponentName;
+HPLcom/android/server/wm/ActivityStarter;->handleStartResult(Lcom/android/server/wm/ActivityRecord;I)Lcom/android/server/wm/ActivityStack;
+HPLcom/android/server/wm/ActivityStarter;->startActivityInner(Lcom/android/server/wm/ActivityRecord;Lcom/android/server/wm/ActivityRecord;Landroid/service/voice/IVoiceInteractionSession;Lcom/android/internal/app/IVoiceInteractor;IZLandroid/app/ActivityOptions;Lcom/android/server/wm/TaskRecord;[Lcom/android/server/wm/ActivityRecord;Z)I
+HPLcom/android/server/wm/ActivityTaskManagerService;->ensureConfigAndVisibilityAfterUpdate(Lcom/android/server/wm/ActivityRecord;I)Z
+HPLcom/android/server/wm/AnimatingActivityRegistry;->endDeferringFinished()V
+HPLcom/android/server/wm/AnimationAdapter;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/android/server/wm/AppTransitionController;->lookForHighestTokenWithFilter(Landroid/util/ArraySet;Landroid/util/ArraySet;Landroid/util/ArraySet;Ljava/util/function/Predicate;)Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/DisplayContent;->findFocusedWindowIfNeeded(I)Lcom/android/server/wm/WindowState;
+HPLcom/android/server/wm/DisplayContent;->getActivityRecord(Landroid/os/IBinder;)Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/DisplayContent;->getParentWindow()Lcom/android/server/wm/WindowState;
+HPLcom/android/server/wm/DisplayContent;->lambda$new$1$DisplayContent(Lcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/DisplayContent;->lambda$new$2$DisplayContent(Lcom/android/server/wm/WindowState;)Z
+HPLcom/android/server/wm/DisplayContent;->lambda$new$3$DisplayContent(Lcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/DisplayContent;->lambda$updateSystemUiVisibility$20(IILcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/DisplayContent;->logsGestureExclusionRestrictions(Lcom/android/server/wm/WindowState;)Z
+HPLcom/android/server/wm/DisplayPolicy;->getCurrentUserResources()Landroid/content/res/Resources;
+HPLcom/android/server/wm/DisplayPolicy;->getStatusBar()Lcom/android/server/wm/WindowState;
+HPLcom/android/server/wm/DisplayPolicy;->lambda$addWindowLw$3$DisplayPolicy(Lcom/android/server/wm/DisplayFrames;Lcom/android/server/wm/WindowState;Landroid/graphics/Rect;)V
+HPLcom/android/server/wm/DisplayPolicy;->lambda$addWindowLw$4$DisplayPolicy(Lcom/android/server/wm/DisplayFrames;Lcom/android/server/wm/WindowState;Landroid/graphics/Rect;)V
+HPLcom/android/server/wm/DisplayPolicy;->lambda$addWindowLw$5$DisplayPolicy(Lcom/android/server/wm/DisplayFrames;Lcom/android/server/wm/WindowState;Landroid/graphics/Rect;)V
+HPLcom/android/server/wm/DisplayPolicy;->lambda$addWindowLw$6$DisplayPolicy(Lcom/android/server/wm/DisplayFrames;Lcom/android/server/wm/WindowState;Landroid/graphics/Rect;)V
+HPLcom/android/server/wm/DisplayPolicy;->lambda$addWindowLw$7$DisplayPolicy(Lcom/android/server/wm/DisplayFrames;Lcom/android/server/wm/WindowState;Landroid/graphics/Rect;)V
+HPLcom/android/server/wm/DisplayPolicy;->lambda$updateSystemUiVisibilityLw$10$DisplayPolicy(IIILandroid/graphics/Rect;Landroid/graphics/Rect;ZLcom/android/server/wm/WindowState;Z)V
+HPLcom/android/server/wm/DisplayRotation;->updateOrientation(IZ)Z
+HPLcom/android/server/wm/DisplayRotation;->updateUserDependentConfiguration(Landroid/content/res/Resources;)V
+HPLcom/android/server/wm/HighRefreshRateBlacklist;->isBlacklisted(Ljava/lang/String;)Z
+HPLcom/android/server/wm/InputManagerCallback;->dispatchPointerCaptureChanged(Landroid/view/IWindow;Z)Z
+HPLcom/android/server/wm/InputManagerCallback;->onPointerDownOutsideFocus(Landroid/os/IBinder;)V
+HPLcom/android/server/wm/InputMonitor;->layoutInputConsumers(II)V
+HPLcom/android/server/wm/InputMonitor;->setFocusedAppLw(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/InsetsStateController;->onControlChanged(ILcom/android/server/wm/InsetsControlTarget;)V
+HPLcom/android/server/wm/LaunchObserverRegistryImpl;->onActivityLaunchFinished([BJ)V
+HPLcom/android/server/wm/RemoteAnimationController$FinishedCallback;->release()V
+HPLcom/android/server/wm/RemoteAnimationController;->lambda$goodToGo$1$RemoteAnimationController([Landroid/view/RemoteAnimationTarget;[Landroid/view/RemoteAnimationTarget;)V
+HPLcom/android/server/wm/RunningTasks;->getTasks(ILjava/util/List;IILjava/util/ArrayList;IZZLandroid/util/ArraySet;)V
+HPLcom/android/server/wm/SplashScreenStartingData;->createStartingSurface(Lcom/android/server/wm/ActivityRecord;)Lcom/android/server/policy/WindowManagerPolicy$StartingSurface;
+HPLcom/android/server/wm/SurfaceAnimator;->lambda$getFinishedCallback$0$SurfaceAnimator(Lcom/android/server/wm/AnimationAdapter;Ljava/lang/Runnable;)V
+HPLcom/android/server/wm/Task;->positionChildAt(ILcom/android/server/wm/ActivityRecord;Z)V
+HPLcom/android/server/wm/TaskRecord;->handlesOrientationChangeFromDescendant()Z
+HPLcom/android/server/wm/TaskRecord;-><init>(Lcom/android/server/wm/ActivityTaskManagerService;ILandroid/content/Intent;Landroid/content/Intent;Ljava/lang/String;Ljava/lang/String;Landroid/content/ComponentName;Landroid/content/ComponentName;ZZZIILjava/lang/String;Ljava/util/ArrayList;JZLandroid/app/ActivityManager$TaskDescription;IIIIILjava/lang/String;IZZZIILandroid/content/pm/ActivityInfo;Landroid/service/voice/IVoiceInteractionSession;Lcom/android/internal/app/IVoiceInteractor;)V
+HPLcom/android/server/wm/TaskStack;->getAnimatingActivityRegistry()Lcom/android/server/wm/AnimatingActivityRegistry;
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->startWallpaperAnimations(Lcom/android/server/wm/WindowManagerService;JJLjava/util/function/Consumer;Ljava/util/ArrayList;)[Landroid/view/RemoteAnimationTarget;
+HPLcom/android/server/wm/WindowContainer$ForAllWindowsConsumerWrapper;-><init>(Lcom/android/server/wm/WindowContainer;Lcom/android/server/wm/WindowContainer$1;)V
+HPLcom/android/server/wm/WindowManagerService;->finishDrawingWindow(Lcom/android/server/wm/Session;Landroid/view/IWindow;Landroid/view/SurfaceControl$Transaction;)V
+HPLcom/android/server/wm/WindowManagerService;->reportSystemGestureExclusionChanged(Lcom/android/server/wm/Session;Landroid/view/IWindow;Ljava/util/List;)V
+HPLcom/android/server/wm/WindowProcessController;->setRunningRemoteAnimation(Z)V
+HPLcom/android/server/wm/WindowProcessController;->shouldSetProfileProc()Z
+HPLcom/android/server/wm/WindowState;->onMergedOverrideConfigurationChanged()V
+HPLcom/android/server/wm/WindowSurfacePlacer;->continueLayout(Z)V
+HPLcom/android/server/wm/WindowSurfacePlacer;->isLayoutDeferred()Z
+HPLcom/google/android/startop/iorap/IorapForwardingService$AppLaunchObserver;->onActivityLaunchFinished([BJ)V
+HPLcom/google/android/startop/iorap/IorapForwardingService$AppLaunchObserver;->onIntentStarted(Landroid/content/Intent;J)V
+HPLcom/google/android/startop/iorap/IorapForwardingService;->invokeRemote(Lcom/google/android/startop/iorap/IIorap;Lcom/google/android/startop/iorap/IorapForwardingService$RemoteRunnable;)Z
+HPLcom/android/server/am/HostingRecord;-><init>(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;IZ)V
+HPLcom/android/server/am/ProcessList;->startProcessLocked(Ljava/lang/String;Landroid/content/pm/ApplicationInfo;ZILcom/android/server/am/HostingRecord;ZZIZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/Runnable;)Lcom/android/server/am/ProcessRecord;
+HPLcom/android/server/am/ProcessRecord;->updateProcessInfo(ZZZ)V
+HPLcom/android/server/appprediction/RemoteAppPredictionService;->lambda$notifyAppTargetEvent$1(Landroid/app/prediction/AppPredictionSessionId;Landroid/app/prediction/AppTargetEvent;Landroid/service/appprediction/IPredictionService;)V
+HPLcom/android/server/audio/SoundEffectsHelper$SfxHandler$1;->run(Z)V
+HPLcom/android/server/input/InputManagerService$InputDevicesChangedListenerRecord;-><init>(Lcom/android/server/input/InputManagerService;ILandroid/hardware/input/IInputDevicesChangedListener;)V
+HPLcom/android/server/pm/PackageManagerServiceUtils;->enforceShellRestriction(Landroid/os/UserManagerInternal;Ljava/lang/String;II)V
+HPLcom/android/server/statusbar/StatusBarManagerService$1;->setSystemUiVisibility(IIIIILandroid/graphics/Rect;Landroid/graphics/Rect;ZLjava/lang/String;)V
+HPLcom/android/server/wm/-$$Lambda$AppTransitionController$o_nkoN7a-ZHaSAgJCQZcboKz9Ig;->test(Ljava/lang/Object;)Z
+HPLcom/android/server/wm/-$$Lambda$AppTransitionController$z5kCoexPNTWFncmRBfeXr6HA2JA;->test(Ljava/lang/Object;)Z
+HPLcom/android/server/wm/-$$Lambda$TaskPersister$8TcnoL7JFvpj8NzBRg91ns5JOBw;-><init>(Lcom/android/server/wm/TaskRecord;)V
+HPLcom/android/server/wm/ActivityRecord;->getAnimationBounds(I)Landroid/graphics/Rect;
+HPLcom/android/server/wm/ActivityRecord;->logStartActivity(ILcom/android/server/wm/TaskRecord;)V
+HPLcom/android/server/wm/ActivityRecord;->shouldAnimate(I)Z
+HPLcom/android/server/wm/ActivityStack;->getRunningTasks(Ljava/util/List;IIIZZLandroid/util/ArraySet;)V
+HPLcom/android/server/wm/ActivityStarter;->computeTargetTask(Lcom/android/server/wm/ActivityRecord;)Lcom/android/server/wm/TaskRecord;
+HPLcom/android/server/wm/ActivityStarter;->deliverToCurrentTopIfNeeded(Lcom/android/server/wm/ActivityStack;)I
+HPLcom/android/server/wm/ActivityStarter;->isAllowedToStart(Lcom/android/server/wm/ActivityRecord;ZLcom/android/server/wm/TaskRecord;)I
+HPLcom/android/server/wm/ActivityStarter;->setInitialState(Lcom/android/server/wm/ActivityRecord;Landroid/app/ActivityOptions;Lcom/android/server/wm/TaskRecord;ZILcom/android/server/wm/ActivityRecord;Landroid/service/voice/IVoiceInteractionSession;Lcom/android/internal/app/IVoiceInteractor;Z)V
+HPLcom/android/server/wm/ActivityStarter;->setNewTask(Lcom/android/server/wm/TaskRecord;)V
+HPLcom/android/server/wm/AnimationAdapter;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/android/server/wm/DisplayRotation;->updateRotationUnchecked(Z)Z
+HPLcom/android/server/wm/RemoteAnimationController;->createRemoteAnimationRecord(Lcom/android/server/wm/ActivityRecord;Landroid/graphics/Point;Landroid/graphics/Rect;Landroid/graphics/Rect;)Lcom/android/server/wm/RemoteAnimationController$RemoteAnimationRecord;
+HPLcom/android/server/wm/RemoteAnimationController;->linkToDeathOfRunner()V
+HPLcom/android/server/wm/RemoteAnimationController;->writeStartDebugStatement()V
+HPLcom/android/server/wm/TaskRecord;->setMinDimensions(Landroid/content/pm/ActivityInfo;)V
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->startWallpaperAnimations(Lcom/android/server/wm/WindowManagerService;JJLjava/util/function/Consumer;Ljava/util/ArrayList;)[Landroid/view/RemoteAnimationTarget;
+HPLcom/android/server/wm/WindowStateAnimator;->finishDrawingLocked(Landroid/view/SurfaceControl$Transaction;)Z
+HPLcom/google/android/startop/iorap/-$$Lambda$IorapForwardingService$AppLaunchObserver$6ikxM-3KospNGDidAY7yA-rECHw;->run(Lcom/google/android/startop/iorap/IIorap;)V
+HPLcom/google/android/startop/iorap/-$$Lambda$IorapForwardingService$AppLaunchObserver$B9wq4q5y7qahY6TuLMO_s8nPIwY;->run(Lcom/google/android/startop/iorap/IIorap;)V
+HPLcom/google/android/startop/iorap/-$$Lambda$IorapForwardingService$AppLaunchObserver$J1AHa-Qs75WQr3stjbN97THbudE;->run(Lcom/google/android/startop/iorap/IIorap;)V
+HPLcom/android/server/am/ProcessList;->newProcessRecordLocked(Landroid/content/pm/ApplicationInfo;Ljava/lang/String;ZILcom/android/server/am/HostingRecord;)Lcom/android/server/am/ProcessRecord;
+HPLcom/android/server/appprediction/RemoteAppPredictionService;->lambda$notifyAppTargetEvent$1(Landroid/app/prediction/AppPredictionSessionId;Landroid/app/prediction/AppTargetEvent;Landroid/service/appprediction/IPredictionService;)V
+HPLcom/android/server/audio/SoundEffectsHelper;->onPlaySoundEffect(II)V
+HPLcom/android/server/LocationManagerService;->isThrottlingExemptLocked(Lcom/android/server/location/CallerIdentity;)Z
+HPLcom/android/server/statusbar/StatusBarManagerService;->setSystemUiVisibility(IIIIILandroid/graphics/Rect;Landroid/graphics/Rect;ZLjava/lang/String;)V
+HPLcom/android/server/wm/AnimationAdapter;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/android/server/wm/RemoteAnimationController$RemoteAnimationAdapterWrapper;->dump(Ljava/io/PrintWriter;Ljava/lang/String;)V
+HPLcom/android/server/wm/RemoteAnimationController$RemoteAnimationRecord;-><init>(Lcom/android/server/wm/RemoteAnimationController;Lcom/android/server/wm/ActivityRecord;Landroid/graphics/Point;Landroid/graphics/Rect;Landroid/graphics/Rect;)V
+HPLcom/android/server/wm/WindowProcessController;->setBoundClientUids(Landroid/util/ArraySet;)V
+HPLcom/google/android/startop/iorap/IorapForwardingService$AppLaunchObserver;->lambda$onActivityLaunched$2$IorapForwardingService$AppLaunchObserver([BILcom/google/android/startop/iorap/IIorap;)V
+HPLcom/google/android/startop/iorap/IorapForwardingService$AppLaunchObserver;->lambda$onActivityLaunchFinished$4$IorapForwardingService$AppLaunchObserver([BJLcom/google/android/startop/iorap/IIorap;)V
+HPLcom/google/android/startop/iorap/IorapForwardingService$AppLaunchObserver;->lambda$onIntentStarted$0$IorapForwardingService$AppLaunchObserver(Landroid/content/Intent;JLcom/google/android/startop/iorap/IIorap;)V
+HPLcom/android/server/statusbar/StatusBarManagerService;->updateUiVisibilityLocked(IIIIILandroid/graphics/Rect;Landroid/graphics/Rect;Z)V
+HPLcom/android/server/wm/AnimationAdapter;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/google/android/startop/iorap/IIorap$Stub$Proxy;->onAppLaunchEvent(Lcom/google/android/startop/iorap/RequestId;Lcom/google/android/startop/iorap/AppLaunchEvent;)V
+HPLcom/google/android/startop/iorap/RequestId;->nextValueForSequence()Lcom/google/android/startop/iorap/RequestId;
+HPLcom/android/server/AlarmManagerService;->decrementAlarmCount(II)V
+HPLcom/android/server/am/ActivityManagerService$4;->newArray(I)[Landroid/content/IntentFilter;
+HPLcom/android/server/am/ActivityManagerService$PidMap;->remove(Lcom/android/server/am/ProcessRecord;)V
+HPLcom/android/server/am/ActivityManagerService;->updateOomAdjLocked(Ljava/lang/String;)V
+HPLcom/android/server/am/ActivityManagerShellCommand$1;-><init>(Lcom/android/server/am/ActivityManagerShellCommand;)V
+HPLcom/android/server/am/ActivityManagerShellCommand;-><init>(Lcom/android/server/am/ActivityManagerService;Z)V
+HPLcom/android/server/am/ActivityManagerShellCommand;->runStartActivity(Ljava/io/PrintWriter;)I
+HPLcom/android/server/am/HostingRecord;-><init>(Ljava/lang/String;Landroid/content/ComponentName;I)V
+HPLcom/android/server/am/PendingIntentController;->registerIntentSenderCancelListener(Landroid/content/IIntentSender;Lcom/android/internal/os/IResultReceiver;)V
+HPLcom/android/server/appprediction/-$$Lambda$AppPredictionManagerService$PredictionManagerServiceStub$vSY20eQq5y5FXrxhhqOTcEmezTs;-><init>(Landroid/app/prediction/AppPredictionSessionId;)V
+HPLcom/android/server/appprediction/-$$Lambda$RemoteAppPredictionService$9DCowUTEF8fYuBlWGxOmP5hTAWA;-><init>(Landroid/app/prediction/AppPredictionSessionId;)V
+HPLcom/android/server/appprediction/RemoteAppPredictionService;->lambda$requestPredictionUpdate$6(Landroid/app/prediction/AppPredictionSessionId;Landroid/service/appprediction/IPredictionService;)V
+HPLcom/android/server/autofill/-$$Lambda$AutofillManagerService$1$1-WNu3tTkxodB_LsZ7dGIlvrPN0;->visit(Ljava/lang/Object;)V
+HPLcom/android/server/autofill/ui/-$$Lambda$AutoFillUI$56AC3ykfo4h_e2LSjdkJ3XQn370;-><init>(Lcom/android/server/autofill/ui/AutoFillUI;Lcom/android/server/autofill/ui/AutoFillUI$AutoFillUiCallback;)V
+HPLcom/android/server/contentsuggestions/-$$Lambda$RemoteContentSuggestionsService$Enqw46SYVKFK9F2xX4qUcIu5_3I;->run(Landroid/os/IInterface;)V
+HPLcom/android/server/contentsuggestions/-$$Lambda$RemoteContentSuggestionsService$eoGnQ2MDLLnW1UBX6wxNE1VBLAk;->run(Landroid/os/IInterface;)V
+HPLcom/android/server/contentsuggestions/-$$Lambda$RemoteContentSuggestionsService$VKh1DoMPNSPjPfnVGdsInmxuqzc;->run(Landroid/os/IInterface;)V
+HPLcom/android/server/contentsuggestions/-$$Lambda$RemoteContentSuggestionsService$yUTbcaYlZCYTmagCkNJ3i2VCkY4;->run(Landroid/os/IInterface;)V
+HPLcom/android/server/contentsuggestions/RemoteContentSuggestionsService;->getServiceInterface(Landroid/os/IBinder;)Landroid/os/IInterface;
+HPLcom/android/server/display/AutomaticBrightnessController;->updateAutoBrightness(ZZ)V
+HPLcom/android/server/display/DisplayPowerController$BrightnessReason;->setModifier(I)V
+HPLcom/android/server/display/DisplayPowerController$BrightnessReason;->setReason(I)V
+HPLcom/android/server/display/DisplayPowerController$BrightnessReason;->toString(I)Ljava/lang/String;
+HPLcom/android/server/display/DisplayPowerController$BrightnessReason;->toString()Ljava/lang/String;
+HPLcom/android/server/media/projection/MediaProjectionManagerService$1;->onProcessDied(II)V
+HPLcom/android/server/net/NetworkPolicyManagerService;->removeUidStateUL(I)Z
+HPLcom/android/server/pm/permission/PermissionManagerService;->addOnPermissionsChangeListener(Landroid/permission/IOnPermissionsChangeListener;)V
+HPLcom/android/server/protolog/ProtoLogImpl;->getSingleInstance()Lcom/android/server/protolog/ProtoLogImpl;
+HPLcom/android/server/soundtrigger/SoundTriggerHelper$PowerSaveModeListener;-><init>(Lcom/android/server/soundtrigger/SoundTriggerHelper;)V
+HPLcom/android/server/statusbar/-$$Lambda$StatusBarManagerService$uF0ibEnnXe7Lxunxb98QQLJjgZM;->run()V
+HPLcom/android/server/statusbar/StatusBarManagerService$UiState;->setSystemUiState(IIILandroid/graphics/Rect;Landroid/graphics/Rect;Z)V
+HPLcom/android/server/statusbar/StatusBarManagerService$UiState;->systemUiStateEquals(IIILandroid/graphics/Rect;Landroid/graphics/Rect;Z)Z
+HPLcom/android/server/usage/UsageStatsDatabase;->filterStats(Lcom/android/server/usage/IntervalStats;)V
+HPLcom/android/server/VibratorService$VibrationInfo;-><init>(JLandroid/os/VibrationEffect;Landroid/os/VibrationEffect;Landroid/media/AudioAttributes;ILjava/lang/String;Ljava/lang/String;)V
+HPLcom/android/server/VibratorService;->getAppOpMode(Lcom/android/server/VibratorService$Vibration;)I
+HPLcom/android/server/VibratorService;->getCurrentIntensityLocked(Lcom/android/server/VibratorService$Vibration;)I
+HPLcom/android/server/VibratorService;->isAllowedToVibrateLocked(Lcom/android/server/VibratorService$Vibration;)Z
+HPLcom/android/server/VibratorService;->vibrate(ILjava/lang/String;Landroid/os/VibrationEffect;Landroid/media/AudioAttributes;Ljava/lang/String;Landroid/os/IBinder;)V
+HPLcom/android/server/wm/-$$Lambda$ActivityRecord$g49I60MBbnNkxHlgA-NR7ALwWTQ;->apply(Ljava/lang/Object;)Z
+HPLcom/android/server/wm/-$$Lambda$ActivityRecord$pBc6yUdDV5IrUd9vt6oCz6QzpiE;->accept(Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$BEx3OWenCvYAaV5h_J2ZkZXhEcY;->accept(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$Zbxkj4wIhcDki6VwBh1kWmSmxqM;-><init>(Lcom/android/server/wm/DisplayPolicy;IIILandroid/graphics/Rect;Landroid/graphics/Rect;ZLcom/android/server/wm/WindowState;I[Lcom/android/internal/view/AppearanceRegion;ZZ)V
+HPLcom/android/server/wm/-$$Lambda$DisplayPolicy$Zbxkj4wIhcDki6VwBh1kWmSmxqM;->run()V
+HPLcom/android/server/wm/-$$Lambda$TaskChangeNotificationController$UexNbaqPy0mc3VxTw2coCctHho8;->accept(Landroid/app/ITaskStackListener;Landroid/os/Message;)V
+HPLcom/android/server/wm/ActivityMetricsLogger;->allWindowsDrawn()Z
+HPLcom/android/server/wm/ActivityRecord;->createAnimationBoundsLayer(Landroid/view/SurfaceControl$Transaction;)Landroid/view/SurfaceControl;
+HPLcom/android/server/wm/ActivityRecord;->destroyed(Ljava/lang/String;)V
+HPLcom/android/server/wm/ActivityRecord;->forAllWindowsUnchecked(Lcom/android/internal/util/ToBooleanFunction;Z)Z
+HPLcom/android/server/wm/ActivityRecord;->getTopFullscreenWindow()Lcom/android/server/wm/WindowState;
+HPLcom/android/server/wm/ActivityRecord;->loadAnimation(Landroid/view/WindowManager$LayoutParams;IZZ)Landroid/view/animation/Animation;
+HPLcom/android/server/wm/ActivityRecord;->notifyAppStopped()V
+HPLcom/android/server/wm/ActivityRecord;->onFirstWindowDrawn(Lcom/android/server/wm/WindowState;Lcom/android/server/wm/WindowStateAnimator;)V
+HPLcom/android/server/wm/ActivityRecord;->onRemovedFromDisplay()V
+HPLcom/android/server/wm/ActivityRecord;->removeDeadWindows()V
+HPLcom/android/server/wm/ActivityRecord;->setClientHidden(Z)V
+HPLcom/android/server/wm/ActivityRecord;->stopFreezingScreenLocked(Z)V
+HPLcom/android/server/wm/ActivityStack;->removeTimeoutsForActivity(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/ActivityStarter;->recycleTask(Lcom/android/server/wm/TaskRecord;Lcom/android/server/wm/ActivityRecord;Lcom/android/server/wm/ActivityRecord;[Lcom/android/server/wm/ActivityRecord;)I
+HPLcom/android/server/wm/ActivityTaskManagerService;->getTaskSnapshot(IZZ)Landroid/app/ActivityManager$TaskSnapshot;
+HPLcom/android/server/wm/AnimationAdapter;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/android/server/wm/DisplayContent;->getWindowCornerRadius()F
+HPLcom/android/server/wm/DisplayPolicy;->convertNonDecorInsetsToStableInsets(Landroid/graphics/Rect;I)V
+HPLcom/android/server/wm/DisplayPolicy;->getInsetsPolicy()Lcom/android/server/wm/InsetsPolicy;
+HPLcom/android/server/wm/DisplayPolicy;->updateLightStatusBarAppearanceLw(ILcom/android/server/wm/WindowState;Lcom/android/server/wm/WindowState;)I
+HPLcom/android/server/wm/InsetsPolicy;->getInsetsForDispatch(Lcom/android/server/wm/WindowState;)Landroid/view/InsetsState;
+HPLcom/android/server/wm/InsetsPolicy;->isHidden(I)Z
+HPLcom/android/server/wm/InsetsPolicy;->updateBarControlTarget(Lcom/android/server/wm/WindowState;)V
+HPLcom/android/server/wm/Task;->getTopFullscreenActivity()Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/TaskRecord;->removeTaskActivitiesLocked(Ljava/lang/String;)V
+HPLcom/android/server/wm/Task;->removeChild(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/TaskSnapshotCache$CacheEntry;-><init>(Landroid/app/ActivityManager$TaskSnapshot;Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/TaskSnapshotController;->createTaskSnapshot(Lcom/android/server/wm/Task;F)Landroid/view/SurfaceControl$ScreenshotGraphicBuffer;
+HPLcom/android/server/wm/TaskSnapshotController;->findAppTokenForSnapshot(Lcom/android/server/wm/Task;)Lcom/android/server/wm/ActivityRecord;
+HPLcom/android/server/wm/TaskSnapshotPersister$DeleteWriteQueueItem;-><init>(Lcom/android/server/wm/TaskSnapshotPersister;II)V
+HPLcom/android/server/wm/TaskSnapshotPersister$StoreWriteQueueItem;-><init>(Lcom/android/server/wm/TaskSnapshotPersister;IILandroid/app/ActivityManager$TaskSnapshot;)V
+HPLcom/android/server/wm/TaskSnapshotPersister$StoreWriteQueueItem;->onQueuedLocked()V
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->lambda$startWallpaperAnimations$0(JJLjava/util/function/Consumer;Ljava/util/ArrayList;Ljava/util/ArrayList;Lcom/android/server/wm/WallpaperWindowToken;)V
+HPLcom/android/server/wm/WallpaperAnimationAdapter;->startWallpaperAnimations(Lcom/android/server/wm/WindowManagerService;JJLjava/util/function/Consumer;Ljava/util/ArrayList;)[Landroid/view/RemoteAnimationTarget;
+HPLcom/android/server/wm/WindowAnimationSpec;->findTranslateAnimation(Landroid/view/animation/Animation;)Landroid/view/animation/TranslateAnimation;
+HPLcom/android/server/wm/WindowProcessControllerMap;->removeProcessFromUidMap(Lcom/android/server/wm/WindowProcessController;)V
+HPLcom/android/server/wm/WindowProcessController;->updateProcessInfo(ZZZ)V
+HPLcom/android/server/wm/WindowState$DeathRecipient;-><init>(Lcom/android/server/wm/WindowState;Lcom/android/server/wm/WindowState$1;)V
+HPLcom/android/server/wm/WindowState$WindowId;-><init>(Lcom/android/server/wm/WindowState;Lcom/android/server/wm/WindowState$1;)V
+HPLcom/google/android/startop/iorap/AppLaunchEvent$ActivityLaunched;->writeToParcelImpl(Landroid/os/Parcel;I)V
+HPLcom/google/android/startop/iorap/AppLaunchEvent$ActivityLaunchFinished;->writeToParcelImpl(Landroid/os/Parcel;I)V
+HPLcom/google/android/startop/iorap/AppLaunchEvent$IntentStarted;->writeToParcelImpl(Landroid/os/Parcel;I)V
+HPLcom/google/android/startop/iorap/AppLaunchEvent;->getTypeIndex()I
+HPLcom/android/server/pm/PackageManagerService;->access$7600(Lcom/android/server/pm/PackageManagerService;Landroid/content/Intent;Ljava/lang/String;IIZI)Landroid/content/pm/ResolveInfo;
+HPLcom/android/server/pm/PackageManagerService;->access$8100(Lcom/android/server/pm/PackageManagerService;II)Z
+HPLcom/android/server/wm/ActivityRecord$Token;->access$100(Lcom/android/server/wm/ActivityRecord$Token;Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/RemoteAnimationController$RemoteAnimationAdapterWrapper;->access$000(Lcom/android/server/wm/RemoteAnimationController$RemoteAnimationAdapterWrapper;)Lcom/android/server/wm/SurfaceAnimator$OnAnimationFinishedCallback;
+HPLcom/android/server/wm/RemoteAnimationController$RemoteAnimationAdapterWrapper;->access$400(Lcom/android/server/wm/RemoteAnimationController$RemoteAnimationAdapterWrapper;)Landroid/graphics/Point;
+HPLcom/android/server/wm/RemoteAnimationController$RemoteAnimationAdapterWrapper;->access$500(Lcom/android/server/wm/RemoteAnimationController$RemoteAnimationAdapterWrapper;)Landroid/graphics/Rect;
+HPLcom/android/server/wm/RemoteAnimationController;->access$100(Lcom/android/server/wm/RemoteAnimationController;)V
+HPLcom/android/server/wm/RemoteAnimationController;->access$300(Lcom/android/server/wm/RemoteAnimationController;)Landroid/view/RemoteAnimationAdapter;
+HPLcom/android/server/wm/TaskPersister$TaskWriteQueueItem;->access$200(Lcom/android/server/wm/TaskPersister$TaskWriteQueueItem;)Lcom/android/server/wm/TaskRecord;
+HPLcom/android/server/wm/TaskPersister;->access$000(I)Ljava/io/File;
+HPLcom/android/server/wm/WindowContainer;->access$100(Lcom/android/server/wm/WindowContainer;)Landroid/util/Pools$SynchronizedPool;
+HPLcom/android/server/wm/WindowManagerService;->access$1600(Lcom/android/server/wm/WindowManagerService;Landroid/os/IBinder;)V
+HPLcom/android/server/pm/ShortcutUser;->logSharingShortcutStats(Lcom/android/internal/logging/MetricsLogger;)V
+HPLcom/android/server/statusbar/StatusBarManagerService;->lambda$topAppWindowChanged$1$StatusBarManagerService(IZZ)V
+HPLcom/android/server/wm/ActivityRecord$Token;->attach(Lcom/android/server/wm/ActivityRecord;)V
+HPLcom/android/server/wm/AnimationAdapter;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/android/server/wm/DisplayPolicy;->lambda$updateSystemUiVisibilityLw$10$DisplayPolicy(IIILandroid/graphics/Rect;Landroid/graphics/Rect;ZLcom/android/server/wm/WindowState;I[Lcom/android/internal/view/AppearanceRegion;ZZ)V
+HPLcom/android/server/wm/InsetsSourceProvider;->hasWindow()Z
+HPLcom/android/server/wm/InsetsStateController;->onBarControlTargetChanged(Lcom/android/server/wm/InsetsControlTarget;Lcom/android/server/wm/InsetsControlTarget;Lcom/android/server/wm/InsetsControlTarget;Lcom/android/server/wm/InsetsControlTarget;)V
+HPLcom/android/server/wm/InsetsStateController;->peekSourceProvider(I)Lcom/android/server/wm/InsetsSourceProvider;
+HPLcom/android/server/wm/TaskPersister$TaskWriteQueueItem;->access$200(Lcom/android/server/wm/TaskPersister$TaskWriteQueueItem;)Lcom/android/server/wm/TaskRecord;
+HPLcom/android/server/wm/WindowContainer;->access$100(Lcom/android/server/wm/WindowContainer;)Landroid/util/Pools$SynchronizedPool;
+HPLcom/android/server/-$$Lambda$AlarmManagerService$2$Eo-D98J-N9R2METkD-12gPs320c;-><init>(Lcom/android/server/AlarmManagerService$2;Landroid/app/IAlarmCompleteListener;)V
+HPLcom/android/server/AlarmManagerService;->access$100(Lcom/android/server/AlarmManagerService;)Lcom/android/server/AlarmManagerService$Injector;
+HPLcom/android/server/AlarmManagerService;->access$2102(Lcom/android/server/AlarmManagerService;J)J
+HPLcom/android/server/AlarmManagerService;->access$2202(Lcom/android/server/AlarmManagerService;J)J
+HPLcom/android/server/AlarmManagerService;->access$2300(Lcom/android/server/AlarmManagerService;)V
+HPLcom/android/server/AlarmManagerService;->access$2400(Lcom/android/server/AlarmManagerService;Lcom/android/server/AlarmManagerService$Alarm;)Z
+HPLcom/android/server/AlarmManagerService;->isExemptFromAppStandby(Lcom/android/server/AlarmManagerService$Alarm;)Z
+HPLcom/android/server/appwidget/AppWidgetServiceImpl$HostId;-><init>(IILjava/lang/String;)V
+HPLcom/android/server/content/ContentService$ObserverCall;->run()V
+HPLcom/android/server/statusbar/-$$Lambda$StatusBarManagerService$uF0ibEnnXe7Lxunxb98QQLJjgZM;-><init>(Lcom/android/server/statusbar/StatusBarManagerService;IZZ)V
+HPLcom/android/server/statusbar/StatusBarManagerService$1;->topAppWindowChanged(IZZ)V
+HPLcom/android/server/statusbar/StatusBarManagerService$UiState;->access$1600(Lcom/android/server/statusbar/StatusBarManagerService$UiState;Z)V
+HPLcom/android/server/statusbar/StatusBarManagerService$UiState;->access$1700(Lcom/android/server/statusbar/StatusBarManagerService$UiState;Z)V
+HPLcom/android/server/statusbar/StatusBarManagerService$UiState;->setFullscreen(Z)V
+HPLcom/android/server/statusbar/StatusBarManagerService$UiState;->setImmersive(Z)V
+HPLcom/android/server/statusbar/StatusBarManagerService;->access$600(Lcom/android/server/statusbar/StatusBarManagerService;IZZ)V
+HPLcom/android/server/statusbar/StatusBarManagerService;->enforceStatusBar()V
+HPLcom/android/server/statusbar/StatusBarManagerService;->getUiState(I)Lcom/android/server/statusbar/StatusBarManagerService$UiState;
+HPLcom/android/server/statusbar/StatusBarManagerService;->topAppWindowChanged(IZZ)V
+HPLcom/android/server/wm/InsetsStateController;->onControlFakeTargetChanged(ILcom/android/server/wm/InsetsControlTarget;)V
+HPLcom/android/server/wm/LocalAnimationAdapter$AnimationSpec;->writeToProto(Landroid/util/proto/ProtoOutputStream;J)V
+HPLcom/android/server/wm/LocalAnimationAdapter;->writeToProto(Landroid/util/proto/ProtoOutputStream;)V
+HPLcom/android/server/wm/PersisterQueue;->access$100(Lcom/android/server/wm/PersisterQueue;)Ljava/util/ArrayList;
+HPLcom/android/server/wm/PersisterQueue;->access$200(Lcom/android/server/wm/PersisterQueue;)Ljava/util/ArrayList;
+HPLcom/android/server/wm/PersisterQueue;->access$300(Lcom/android/server/wm/PersisterQueue;)V
+HPLcom/android/server/wm/TaskSnapshotPersister;->access$100(Lcom/android/server/wm/TaskSnapshotPersister;)Ljava/lang/Object;
+HPLcom/android/server/wm/TaskSnapshotPersister;->access$200(Lcom/android/server/wm/TaskSnapshotPersister;)Z
+HPLcom/android/server/wm/TaskSnapshotPersister;->access$300(Lcom/android/server/wm/TaskSnapshotPersister;)Ljava/util/ArrayDeque;
+HPLcom/android/server/wm/TaskSnapshotPersister;->access$402(Lcom/android/server/wm/TaskSnapshotPersister;Z)Z
+HPLcom/android/server/wm/WindowAnimationSpec;->findTranslateAnimation(Landroid/view/animation/Animation;)Landroid/view/animation/TranslateAnimation;
+HPLcom/android/server/wm/WindowAnimationSpec;->writeToProtoInner(Landroid/util/proto/ProtoOutputStream;)V
+HPLcom/android/server/wm/WindowContainer;->access$100(Lcom/android/server/wm/WindowContainer;)Landroid/util/Pools$SynchronizedPool;
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 7d129ea..1fc4751 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -197,8 +197,20 @@
         if ((type & SaveInfo.SAVE_DATA_TYPE_ADDRESS) != 0) {
             types.add(context.getString(R.string.autofill_save_type_address));
         }
-        if ((type & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) {
+
+        // fallback to generic card type if set multiple types
+        final int cardTypeMask = SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD
+                        | SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD
+                        | SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD;
+        final int count = Integer.bitCount(type & cardTypeMask);
+        if (count > 1 || (type & SaveInfo.SAVE_DATA_TYPE_GENERIC_CARD) != 0) {
+            types.add(context.getString(R.string.autofill_save_type_generic_card));
+        } else if ((type & SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD) != 0) {
+            types.add(context.getString(R.string.autofill_save_type_payment_card));
+        } else if ((type & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) {
             types.add(context.getString(R.string.autofill_save_type_credit_card));
+        } else if ((type & SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD) != 0) {
+            types.add(context.getString(R.string.autofill_save_type_debit_card));
         }
         if ((type & SaveInfo.SAVE_DATA_TYPE_USERNAME) != 0) {
             types.add(context.getString(R.string.autofill_save_type_username));
@@ -269,7 +281,9 @@
         noButton.setOnClickListener((v) -> mListener.onCancel(info.getNegativeActionListener()));
 
         final TextView yesButton = view.findViewById(R.id.autofill_save_yes);
-        if (isUpdate) {
+        if (info.getPositiveActionStyle() == SaveInfo.POSITIVE_BUTTON_STYLE_CONTINUE) {
+            yesButton.setText(R.string.autofill_continue_yes);
+        } else if (isUpdate) {
             yesButton.setText(R.string.autofill_update_yes);
         }
         yesButton.setOnClickListener((v) -> mListener.onSave());
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index c8dbb36..27824af 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -18,11 +18,13 @@
 
 import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE;
 import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
+import static android.service.contentcapture.ContentCaptureService.setClientState;
 import static android.view.contentcapture.ContentCaptureHelper.toList;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_FALSE;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_OK;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_SECURITY_EXCEPTION;
 import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_TRUE;
+import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
 
 import static com.android.internal.util.SyncResultReceiver.bundleFor;
 
@@ -520,6 +522,17 @@
         return true;
     }
 
+    @GuardedBy("mLock")
+    private boolean isDefaultServiceLocked(int userId) {
+        final String defaultServiceName = mServiceNameResolver.getDefaultServiceName(userId);
+        if (defaultServiceName == null) {
+            return false;
+        }
+
+        final String currentServiceName = mServiceNameResolver.getServiceName(userId);
+        return defaultServiceName.equals(currentServiceName);
+    }
+
     @Override // from AbstractMasterSystemService
     protected void dumpLocked(String prefix, PrintWriter pw) {
         super.dumpLocked(prefix, pw);
@@ -557,6 +570,10 @@
 
             synchronized (mLock) {
                 final ContentCapturePerUserService service = getServiceForUserLocked(userId);
+                if (!isDefaultServiceLocked(userId) && !isCalledByServiceLocked("startSession()")) {
+                    setClientState(result, STATE_DISABLED, /* binder= */ null);
+                    return;
+                }
                 service.startSessionLocked(activityToken, activityPresentationInfo, sessionId,
                         Binder.getCallingUid(), flags, result);
             }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 4f4e47a..3067beb 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -21,6 +21,7 @@
     cmd: "$(location protologtool) transform-protolog-calls " +
       "--protolog-class com.android.server.protolog.common.ProtoLog " +
       "--protolog-impl-class com.android.server.protolog.ProtoLogImpl " +
+      "--protolog-cache-class 'com.android.server.protolog.ProtoLog$$Cache' " +
       "--loggroups-class com.android.server.wm.ProtoLogGroup " +
       "--loggroups-jar $(location :services.core.wm.protologgroups) " +
       "--output-srcjar $(out) " +
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
similarity index 88%
rename from core/java/android/app/usage/UsageStatsManagerInternal.java
rename to services/core/java/android/app/usage/UsageStatsManagerInternal.java
index b3260c4..6641b5b 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -23,6 +23,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
+
 import java.util.List;
 import java.util.Set;
 
@@ -153,47 +155,6 @@
      */
     public abstract int[] getIdleUidsForUser(@UserIdInt int userId);
 
-    /**
-     * @return True if currently app idle parole mode is on.  This means all idle apps are allow to
-     * run for a short period of time.
-     */
-    public abstract boolean isAppIdleParoleOn();
-
-    /**
-     * Sets up a listener for changes to packages being accessed.
-     * @param listener A listener within the system process.
-     */
-    public abstract void addAppIdleStateChangeListener(
-            AppIdleStateChangeListener listener);
-
-    /**
-     * Removes a listener that was previously added for package usage state changes.
-     * @param listener The listener within the system process to remove.
-     */
-    public abstract void removeAppIdleStateChangeListener(
-            AppIdleStateChangeListener listener);
-
-    public static abstract class AppIdleStateChangeListener {
-
-        /** Callback to inform listeners that the idle state has changed to a new bucket. */
-        public abstract void onAppIdleStateChanged(String packageName, @UserIdInt int userId,
-                boolean idle, int bucket, int reason);
-
-        /**
-         * Callback to inform listeners that the parole state has changed. This means apps are
-         * allowed to do work even if they're idle or in a low bucket.
-         */
-        public abstract void onParoleStateChanged(boolean isParoleOn);
-
-        /**
-         * Optional callback to inform the listener that the app has transitioned into
-         * an active state due to user interaction.
-         */
-        public void onUserInteractionStarted(String packageName, @UserIdInt int userId) {
-            // No-op by default
-        }
-    }
-
     /**  Backup/Restore API */
     public abstract byte[] getBackupPayload(@UserIdInt int userId, String key);
 
diff --git a/core/java/android/os/UserManagerInternal.java b/services/core/java/android/os/UserManagerInternal.java
similarity index 99%
rename from core/java/android/os/UserManagerInternal.java
rename to services/core/java/android/os/UserManagerInternal.java
index 59fb3d9..e5f8b49 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/services/core/java/android/os/UserManagerInternal.java
@@ -11,7 +11,7 @@
  * 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
+ * limitations under the License.
  */
 package android.os;
 
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 9a97ddb..ff0044f 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -47,6 +47,7 @@
 import android.content.pm.PermissionInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -98,6 +99,8 @@
 import com.android.internal.util.LocalLog;
 import com.android.internal.util.StatLogger;
 import com.android.server.AppStateTracker.Listener;
+import com.android.server.usage.AppStandbyInternal;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
@@ -1564,6 +1567,7 @@
                     Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT, UserHandle.ALL);
 
             mClockReceiver = mInjector.getClockReceiver(this);
+            new ChargingReceiver();
             new InteractiveStateReceiver();
             new UninstallReceiver();
 
@@ -1597,7 +1601,9 @@
                         LocalServices.getService(DeviceIdleInternal.class);
                 mUsageStatsManagerInternal =
                         LocalServices.getService(UsageStatsManagerInternal.class);
-                mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
+                AppStandbyInternal appStandbyInternal =
+                        LocalServices.getService(AppStandbyInternal.class);
+                appStandbyInternal.addListener(new AppStandbyTracker());
 
                 mAppStateTracker = LocalServices.getService(AppStateTracker.class);
                 mAppStateTracker.addListener(mForceAppStandbyListener);
@@ -4148,7 +4154,7 @@
         public static final int LISTENER_TIMEOUT = 3;
         public static final int REPORT_ALARMS_ACTIVE = 4;
         public static final int APP_STANDBY_BUCKET_CHANGED = 5;
-        public static final int APP_STANDBY_PAROLE_CHANGED = 6;
+        public static final int CHARGING_STATUS_CHANGED = 6;
         public static final int REMOVE_FOR_STOPPED = 7;
         public static final int UNREGISTER_CANCEL_LISTENER = 8;
 
@@ -4206,7 +4212,7 @@
                     }
                     break;
 
-                case APP_STANDBY_PAROLE_CHANGED:
+                case CHARGING_STATUS_CHANGED:
                     synchronized (mLock) {
                         mAppStandbyParole = (Boolean) msg.obj;
                         if (reorderAlarmsBasedOnStandbyBuckets(null)) {
@@ -4247,6 +4253,37 @@
         }
     }
 
+    @VisibleForTesting
+    class ChargingReceiver extends BroadcastReceiver {
+        ChargingReceiver() {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(BatteryManager.ACTION_CHARGING);
+            filter.addAction(BatteryManager.ACTION_DISCHARGING);
+            getContext().registerReceiver(this, filter);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            final boolean charging;
+            if (BatteryManager.ACTION_CHARGING.equals(action)) {
+                if (DEBUG_STANDBY) {
+                    Slog.d(TAG, "Device is charging.");
+                }
+                charging = true;
+            } else {
+                if (DEBUG_STANDBY) {
+                    Slog.d(TAG, "Disconnected from power.");
+                }
+                charging = false;
+            }
+            mHandler.removeMessages(AlarmHandler.CHARGING_STATUS_CHANGED);
+            mHandler.obtainMessage(AlarmHandler.CHARGING_STATUS_CHANGED, charging)
+                    .sendToTarget();
+        }
+    }
+
+    @VisibleForTesting
     class ClockReceiver extends BroadcastReceiver {
         public ClockReceiver() {
             IntentFilter filter = new IntentFilter();
@@ -4429,13 +4466,13 @@
 
         @Override public void onUidCachedChanged(int uid, boolean cached) {
         }
-    };
+    }
 
     /**
      * Tracking of app assignments to standby buckets
      */
     private final class AppStandbyTracker extends
-            UsageStatsManagerInternal.AppIdleStateChangeListener {
+            AppIdleStateChangeListener {
         @Override
         public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
                 boolean idle, int bucket, int reason) {
@@ -4447,18 +4484,7 @@
             mHandler.obtainMessage(AlarmHandler.APP_STANDBY_BUCKET_CHANGED, userId, -1, packageName)
                     .sendToTarget();
         }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            if (DEBUG_STANDBY) {
-                Slog.d(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
-            }
-            mHandler.removeMessages(AlarmHandler.APP_STANDBY_BUCKET_CHANGED);
-            mHandler.removeMessages(AlarmHandler.APP_STANDBY_PAROLE_CHANGED);
-            mHandler.obtainMessage(AlarmHandler.APP_STANDBY_PAROLE_CHANGED,
-                    Boolean.valueOf(isParoleOn)).sendToTarget();
-        }
-    };
+    }
 
     private final Listener mForceAppStandbyListener = new Listener() {
         @Override
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 2c67c50..5eff2c5 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -24,7 +24,6 @@
 import android.app.IUidObserver;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
-import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -58,6 +57,8 @@
 import com.android.internal.util.StatLogger;
 import com.android.server.AppStateTrackerProto.ExemptedPackage;
 import com.android.server.AppStateTrackerProto.RunAnyInBackgroundRestrictedPackages;
+import com.android.server.usage.AppStandbyInternal;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -71,8 +72,7 @@
  * - Temporary power save whitelist
  * - Global "force all apps standby" mode enforced by battery saver.
  *
- * Test:
-  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
+ * Test: atest com.android.server.AppStateTrackerTest
  */
 public class AppStateTracker {
     private static final String TAG = "AppStateTracker";
@@ -90,7 +90,7 @@
     IAppOpsService mAppOpsService;
     PowerManagerInternal mPowerManagerInternal;
     StandbyTracker mStandbyTracker;
-    UsageStatsManagerInternal mUsageStatsManagerInternal;
+    AppStandbyInternal mAppStandbyInternal;
 
     private final MyHandler mHandler;
 
@@ -421,8 +421,7 @@
             mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
             mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
             mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
-            mUsageStatsManagerInternal = Preconditions.checkNotNull(
-                    injectUsageStatsManagerInternal());
+            mAppStandbyInternal = Preconditions.checkNotNull(injectAppStandbyInternal());
 
             mFlagsObserver = new FeatureFlagsObserver();
             mFlagsObserver.register();
@@ -430,7 +429,7 @@
             mForceAllAppStandbyForSmallBattery =
                     mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
             mStandbyTracker = new StandbyTracker();
-            mUsageStatsManagerInternal.addAppIdleStateChangeListener(mStandbyTracker);
+            mAppStandbyInternal.addListener(mStandbyTracker);
 
             try {
                 mIActivityManager.registerUidObserver(new UidObserver(),
@@ -495,8 +494,8 @@
     }
 
     @VisibleForTesting
-    UsageStatsManagerInternal injectUsageStatsManagerInternal() {
-        return LocalServices.getService(UsageStatsManagerInternal.class);
+    AppStandbyInternal injectAppStandbyInternal() {
+        return LocalServices.getService(AppStandbyInternal.class);
     }
 
     @VisibleForTesting
@@ -710,10 +709,6 @@
                 mHandler.notifyExemptChanged();
             }
         }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-        }
     }
 
     private Listener[] cloneListeners() {
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index d18b4f6..a33fcd5 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -720,6 +720,8 @@
         event.putInt(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
         event.putInt(BatteryManager.EXTRA_PLUGGED, mPlugType);
         event.putInt(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltage);
+        event.putInt(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperature);
+        event.putInt(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounter);
         event.putLong(BatteryManager.EXTRA_EVENT_TIMESTAMP, now);
 
         boolean queueWasEmpty = mBatteryLevelsEventQueue.isEmpty();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0bb72cb..ce0e9e7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -26,6 +26,7 @@
 import static android.net.ConnectivityManager.TYPE_VPN;
 import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
+import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
@@ -528,6 +529,15 @@
     private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 45;
 
     /**
+     * Event for NetworkMonitor to inform ConnectivityService that the probe status has changed.
+     * Both of the arguments are bitmasks, and the value of bits come from
+     * INetworkMonitor.NETWORK_VALIDATION_PROBE_*.
+     * arg1 = A bitmask to describe which probes are completed.
+     * arg2 = A bitmask to describe which probes are successful.
+     */
+    public static final int EVENT_PROBE_STATUS_CHANGED = 46;
+
+    /**
      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
      * should be shown.
      */
@@ -2663,6 +2673,41 @@
             switch (msg.what) {
                 default:
                     return false;
+                case EVENT_PROBE_STATUS_CHANGED: {
+                    final Integer netId = (Integer) msg.obj;
+                    final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
+                    if (nai == null) {
+                        break;
+                    }
+                    final boolean probePrivateDnsCompleted =
+                            ((msg.arg1 & NETWORK_VALIDATION_PROBE_PRIVDNS) != 0);
+                    final boolean privateDnsBroken =
+                            ((msg.arg2 & NETWORK_VALIDATION_PROBE_PRIVDNS) == 0);
+                    if (probePrivateDnsCompleted) {
+                        if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) {
+                            nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken);
+                            final int oldScore = nai.getCurrentScore();
+                            updateCapabilities(oldScore, nai, nai.networkCapabilities);
+                        }
+                        // Only show the notification when the private DNS is broken and the
+                        // PRIVATE_DNS_BROKEN notification hasn't shown since last valid.
+                        if (privateDnsBroken && !nai.networkMisc.hasShownBroken) {
+                            showNetworkNotification(nai, NotificationType.PRIVATE_DNS_BROKEN);
+                        }
+                        nai.networkMisc.hasShownBroken = privateDnsBroken;
+                    } else if (nai.networkCapabilities.isPrivateDnsBroken()) {
+                        // If probePrivateDnsCompleted is false but nai.networkCapabilities says
+                        // private DNS is broken, it means this network is being reevaluated.
+                        // Either probing private DNS is not necessary any more or it hasn't been
+                        // done yet. In either case, the networkCapabilities should be updated to
+                        // reflect the new status.
+                        nai.networkCapabilities.setPrivateDnsBroken(false);
+                        final int oldScore = nai.getCurrentScore();
+                        updateCapabilities(oldScore, nai, nai.networkCapabilities);
+                        nai.networkMisc.hasShownBroken = false;
+                    }
+                    break;
+                }
                 case EVENT_NETWORK_TESTED: {
                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                     if (nai == null) break;
@@ -2705,14 +2750,20 @@
                         if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
                         if (valid) {
                             handleFreshlyValidatedNetwork(nai);
-                            // Clear NO_INTERNET, PARTIAL_CONNECTIVITY and LOST_INTERNET
-                            // notifications if network becomes valid.
+                            // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and
+                            // LOST_INTERNET notifications if network becomes valid.
                             mNotifier.clearNotification(nai.network.netId,
                                     NotificationType.NO_INTERNET);
                             mNotifier.clearNotification(nai.network.netId,
                                     NotificationType.LOST_INTERNET);
                             mNotifier.clearNotification(nai.network.netId,
                                     NotificationType.PARTIAL_CONNECTIVITY);
+                            mNotifier.clearNotification(nai.network.netId,
+                                    NotificationType.PRIVATE_DNS_BROKEN);
+                            // If network becomes valid, the hasShownBroken should be reset for
+                            // that network so that the notification will be fired when the private
+                            // DNS is broken again.
+                            nai.networkMisc.hasShownBroken = false;
                         }
                     } else if (partialConnectivityChanged) {
                         updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
@@ -2863,6 +2914,13 @@
         }
 
         @Override
+        public void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) {
+            mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
+                    EVENT_PROBE_STATUS_CHANGED,
+                    probesCompleted, probesSucceeded, new Integer(mNetId)));
+        }
+
+        @Override
         public void showProvisioningNotification(String action, String packageName) {
             final Intent intent = new Intent(action);
             intent.setPackage(packageName);
@@ -3679,6 +3737,11 @@
                 // High priority because it is only displayed for explicitly selected networks.
                 highPriority = true;
                 break;
+            case PRIVATE_DNS_BROKEN:
+                action = Settings.ACTION_WIRELESS_SETTINGS;
+                // High priority because we should let user know why there is no internet.
+                highPriority = true;
+                break;
             case LOST_INTERNET:
                 action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
                 // High priority because it could help the user avoid unexpected data usage.
@@ -3696,7 +3759,7 @@
         }
 
         Intent intent = new Intent(action);
-        if (type != NotificationType.LOGGED_IN) {
+        if (type != NotificationType.LOGGED_IN && type != NotificationType.PRIVATE_DNS_BROKEN) {
             intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intent.setClassName("com.android.settings",
@@ -5162,6 +5225,13 @@
         ns.assertValidFromUid(Binder.getCallingUid());
     }
 
+    private void ensureValid(NetworkCapabilities nc) {
+        ensureValidNetworkSpecifier(nc);
+        if (nc.isPrivateDnsBroken()) {
+            throw new IllegalArgumentException("Can't request broken private DNS");
+        }
+    }
+
     @Override
     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
             Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
@@ -5195,7 +5265,7 @@
         if (timeoutMs < 0) {
             throw new IllegalArgumentException("Bad timeout specified");
         }
-        ensureValidNetworkSpecifier(networkCapabilities);
+        ensureValid(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
                 nextNetworkRequestId(), type);
@@ -5337,7 +5407,7 @@
         // There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
         // can't request networks.
         restrictBackgroundRequestForCaller(nc);
-        ensureValidNetworkSpecifier(nc);
+        ensureValid(nc);
 
         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
@@ -5355,7 +5425,7 @@
         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
             enforceAccessPermission();
         }
-        ensureValidNetworkSpecifier(networkCapabilities);
+        ensureValid(networkCapabilities);
         ensureSufficientPermissionsForRequest(networkCapabilities,
                 Binder.getCallingPid(), Binder.getCallingUid());
 
@@ -5841,6 +5911,7 @@
         } else {
             newNc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
         }
+        newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
 
         return newNc;
     }
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 18009e1..190e6cf 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -115,7 +115,8 @@
     }
 
     @Override
-    public boolean startInstallation(long systemSize, long userdataSize) throws RemoteException {
+    public boolean startInstallation(String name, long size, boolean readOnly)
+            throws RemoteException {
         // priority from high to low: sysprop -> sdcard -> /data
         String path = SystemProperties.get("os.aot.path");
         if (path.isEmpty()) {
@@ -137,11 +138,18 @@
             }
             Slog.i(TAG, "startInstallation -> " + path);
         }
+        IGsiService service = getGsiService();
         GsiInstallParams installParams = new GsiInstallParams();
         installParams.installDir = path;
-        installParams.gsiSize = systemSize;
-        installParams.userdataSize = userdataSize;
-        return getGsiService().beginGsiInstall(installParams) == 0;
+        installParams.name = name;
+        installParams.size = size;
+        installParams.wipe = readOnly;
+        installParams.readOnly = readOnly;
+        if (service.beginGsiInstall(installParams) != 0) {
+            Slog.i(TAG, "Failed to install " + name);
+            return false;
+        }
+        return true;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/GnssManagerService.java b/services/core/java/com/android/server/GnssManagerService.java
index 44a8234..274e2f1 100644
--- a/services/core/java/com/android/server/GnssManagerService.java
+++ b/services/core/java/com/android/server/GnssManagerService.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -300,7 +301,7 @@
      * @return true if callback is successfully added, false otherwise
      */
     public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
-            @NonNull String listenerIdentity) {
+            @Nullable String featureId, @NonNull String listenerIdentity) {
         mContext.enforceCallingPermission(
                 android.Manifest.permission.LOCATION_HARDWARE,
                 "Location Hardware permission not granted to access hardware batching");
@@ -319,7 +320,7 @@
 
         CallerIdentity callerIdentity =
                 new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName,
-                        listenerIdentity);
+                        featureId, listenerIdentity);
         synchronized (mGnssBatchingLock) {
             mGnssBatchingCallback = callback;
             mGnssBatchingDeathCallback =
@@ -497,6 +498,7 @@
     private <TListener extends IInterface> boolean addGnssDataListenerLocked(
             TListener listener,
             String packageName,
+            @Nullable String featureId,
             @NonNull String listenerIdentifier,
             RemoteListenerHelper<TListener> gnssDataProvider,
             ArrayMap<IBinder,
@@ -517,7 +519,7 @@
 
         CallerIdentity callerIdentity =
                 new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName,
-                        listenerIdentifier);
+                        featureId, listenerIdentifier);
         LinkedListener<TListener> linkedListener =
                 new LocationManagerServiceUtils.LinkedListener<>(
                         listener, listenerIdentifier, callerIdentity, binderDeathCallback);
@@ -605,11 +607,13 @@
      * @param packageName name of requesting package
      * @return true if listener is successfully registered, false otherwise
      */
-    public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName) {
+    public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
+            @Nullable String featureId) {
         synchronized (mGnssStatusListeners) {
             return addGnssDataListenerLocked(
                     listener,
                     packageName,
+                    featureId,
                     "Gnss status",
                     mGnssStatusProvider,
                     mGnssStatusListeners,
@@ -636,12 +640,13 @@
      * @return true if listener is successfully added, false otherwise
      */
     public boolean addGnssMeasurementsListener(
-            IGnssMeasurementsListener listener, String packageName,
+            IGnssMeasurementsListener listener, String packageName, @Nullable String featureId,
             @NonNull String listenerIdentifier) {
         synchronized (mGnssMeasurementsListeners) {
             return addGnssDataListenerLocked(
                     listener,
                     packageName,
+                    featureId,
                     listenerIdentifier,
                     mGnssMeasurementsProvider,
                     mGnssMeasurementsListeners,
@@ -695,11 +700,12 @@
      */
     public boolean addGnssNavigationMessageListener(
             IGnssNavigationMessageListener listener, String packageName,
-            @NonNull String listenerIdentifier) {
+            @Nullable String featureId, @NonNull String listenerIdentifier) {
         synchronized (mGnssNavigationMessageListeners) {
             return addGnssDataListenerLocked(
                     listener,
                     packageName,
+                    featureId,
                     listenerIdentifier,
                     mGnssNavigationMessageProvider,
                     mGnssNavigationMessageListeners,
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index aa22feb..0a63bf8 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -62,8 +62,10 @@
 import android.location.LocationTime;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
 import android.os.PowerManagerInternal;
@@ -119,6 +121,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
 
 /**
  * The service class that manages LocationProviders and issues location
@@ -145,11 +148,12 @@
     private static final String FUSED_LOCATION_SERVICE_ACTION =
             "com.android.location.service.FusedLocationProvider";
 
-    private static final long NANOS_PER_MILLI = 1000000L;
-
     // The maximum interval a location request can have and still be considered "high power".
     private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
 
+    // maximum age of a location before it is no longer considered "current"
+    private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
+
     private static final int FOREGROUND_IMPORTANCE_CUTOFF
             = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
 
@@ -996,6 +1000,12 @@
 
         @Override
         public void onReportLocation(Location location) {
+            // likelihood of a 0,0 bug is far greater than this being a valid location
+            if (!isMock() && location.getLatitude() == 0 && location.getLongitude() == 0) {
+                Slog.w(TAG, "blocking 0,0 location from " + mName + " provider");
+                return;
+            }
+
             synchronized (mLock) {
                 handleLocationChangedLocked(location, this);
             }
@@ -1223,9 +1233,9 @@
         PowerManager.WakeLock mWakeLock;
 
         private Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
-                String packageName, WorkSource workSource, boolean hideFromAppOps,
-                @NonNull String listenerIdentifier) {
-            super(new CallerIdentity(uid, pid, packageName, listenerIdentifier),
+                String packageName, @Nullable String featureId, WorkSource workSource,
+                boolean hideFromAppOps, @NonNull String listenerIdentifier) {
+            super(new CallerIdentity(uid, pid, packageName, featureId, listenerIdentifier),
                     "LocationListener");
             mListener = listener;
             mPendingIntent = intent;
@@ -1350,7 +1360,8 @@
             if (!currentlyMonitoring) {
                 if (allowMonitoring) {
                     return mAppOps.startOpNoThrow(op, mCallerIdentity.mUid,
-                            mCallerIdentity.mPackageName) == AppOpsManager.MODE_ALLOWED;
+                            mCallerIdentity.mPackageName, false, mCallerIdentity.mFeatureId, null)
+                            == AppOpsManager.MODE_ALLOWED;
                 }
             } else {
                 if (!allowMonitoring
@@ -1535,11 +1546,11 @@
 
     @Override
     public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
-            String listenerIdentifier) {
+            String featureId, String listenerIdentifier) {
         Preconditions.checkNotNull(listenerIdentifier);
 
         return mGnssManagerService == null ? false : mGnssManagerService.addGnssBatchingCallback(
-                callback, packageName, listenerIdentifier);
+                callback, packageName, featureId, listenerIdentifier);
     }
 
     @Override
@@ -1702,10 +1713,10 @@
     }
 
     private boolean reportLocationAccessNoThrow(int pid, int uid, String packageName,
-            int allowedResolutionLevel, @Nullable String message) {
+            @Nullable String featureId, int allowedResolutionLevel, @Nullable String message) {
         int op = resolutionLevelToOp(allowedResolutionLevel);
         if (op >= 0) {
-            if (mAppOps.noteOpNoThrow(op, uid, packageName, message)
+            if (mAppOps.noteOpNoThrow(op, uid, packageName, featureId, message)
                     != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
@@ -2139,12 +2150,12 @@
 
     @GuardedBy("mLock")
     private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
-            String packageName, WorkSource workSource, boolean hideFromAppOps,
-            @NonNull String listenerIdentifier) {
+            String packageName, @Nullable String featureId, WorkSource workSource,
+            boolean hideFromAppOps, @NonNull String listenerIdentifier) {
         IBinder binder = listener.asBinder();
         Receiver receiver = mReceivers.get(binder);
         if (receiver == null) {
-            receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
+            receiver = new Receiver(listener, null, pid, uid, packageName, featureId, workSource,
                     hideFromAppOps, listenerIdentifier);
             if (!receiver.linkToListenerDeathNotificationLocked(
                     receiver.getListener().asBinder())) {
@@ -2157,10 +2168,11 @@
 
     @GuardedBy("mLock")
     private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
-            WorkSource workSource, boolean hideFromAppOps, @NonNull String listenerIdentifier) {
+            @Nullable String featureId, WorkSource workSource, boolean hideFromAppOps,
+            @NonNull String listenerIdentifier) {
         Receiver receiver = mReceivers.get(intent);
         if (receiver == null) {
-            receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
+            receiver = new Receiver(null, intent, pid, uid, packageName, featureId, workSource,
                     hideFromAppOps, listenerIdentifier);
             mReceivers.put(intent, receiver);
         }
@@ -2223,7 +2235,8 @@
 
     @Override
     public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
-            PendingIntent intent, String packageName, String listenerIdentifier) {
+            PendingIntent intent, String packageName, String featureId,
+            String listenerIdentifier) {
         Preconditions.checkNotNull(listenerIdentifier);
 
         synchronized (mLock) {
@@ -2279,11 +2292,11 @@
 
                 Receiver receiver;
                 if (intent != null) {
-                    receiver = getReceiverLocked(intent, pid, uid, packageName, workSource,
-                            hideFromAppOps, listenerIdentifier);
+                    receiver = getReceiverLocked(intent, pid, uid, packageName, featureId,
+                            workSource, hideFromAppOps, listenerIdentifier);
                 } else {
-                    receiver = getReceiverLocked(listener, pid, uid, packageName, workSource,
-                            hideFromAppOps, listenerIdentifier);
+                    receiver = getReceiverLocked(listener, pid, uid, packageName, featureId,
+                            workSource, hideFromAppOps, listenerIdentifier);
                 }
                 requestLocationUpdatesLocked(sanitizedRequest, receiver, uid, packageName);
             } finally {
@@ -2352,9 +2365,10 @@
         synchronized (mLock) {
             Receiver receiver;
             if (intent != null) {
-                receiver = getReceiverLocked(intent, pid, uid, packageName, null, false, "");
+                receiver = getReceiverLocked(intent, pid, uid, packageName, null, null, false, "");
             } else {
-                receiver = getReceiverLocked(listener, pid, uid, packageName, null, false, "");
+                receiver = getReceiverLocked(listener, pid, uid, packageName, null, null, false,
+                        "");
             }
 
             long identity = Binder.clearCallingIdentity();
@@ -2398,7 +2412,7 @@
     }
 
     @Override
-    public Location getLastLocation(LocationRequest r, String packageName) {
+    public Location getLastLocation(LocationRequest r, String packageName, String featureId) {
         synchronized (mLock) {
             LocationRequest request = r != null ? r : DEFAULT_LOCATION_REQUEST;
             int allowedResolutionLevel = getCallerAllowedResolutionLevel();
@@ -2450,8 +2464,8 @@
 
                 // Don't return stale location to apps with foreground-only location permission.
                 String op = resolutionLevelToOpStr(allowedResolutionLevel);
-                long locationAgeMs = SystemClock.elapsedRealtime()
-                        - location.getElapsedRealtimeNanos() / NANOS_PER_MILLI;
+                long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
+                        SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
                 if ((locationAgeMs > Settings.Global.getLong(
                         mContext.getContentResolver(),
                         Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
@@ -2473,8 +2487,8 @@
                 }
                 // Don't report location access if there is no last location to deliver.
                 if (lastLocation != null) {
-                    if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel,
-                            null)) {
+                    if (!reportLocationAccessNoThrow(pid, uid, packageName, featureId,
+                            allowedResolutionLevel, null)) {
                         if (D) {
                             Log.d(TAG, "not returning last loc for no op app: " + packageName);
                         }
@@ -2489,6 +2503,57 @@
     }
 
     @Override
+    public boolean getCurrentLocation(LocationRequest locationRequest,
+            ICancellationSignal remoteCancellationSignal, ILocationListener listener,
+            String packageName, String featureId, String listenerIdentifier) {
+        // side effect of validating locationRequest and packageName
+        Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
+        if (lastLocation != null) {
+            long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
+                    SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
+
+            long identity = Binder.clearCallingIdentity();
+            try {
+                if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
+                    try {
+                        listener.onLocationChanged(lastLocation);
+                        return true;
+                    } catch (RemoteException e) {
+                        Log.w(TAG, e);
+                        return false;
+                    }
+                }
+
+                // packageName already validated by getLastLocation() call above
+                boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
+                        mActivityManager.getPackageImportance(packageName));
+                if (!foreground) {
+                    long backgroundThrottleIntervalMs = Settings.Global.getLong(
+                            mContext.getContentResolver(),
+                            Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
+                            DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+                    if (locationAgeMs < backgroundThrottleIntervalMs) {
+                        // not allowed to request new locations, so we can't return anything
+                        return false;
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        requestLocationUpdates(locationRequest, listener, null, packageName, featureId,
+                listenerIdentifier);
+        CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
+                remoteCancellationSignal);
+        if (cancellationSignal != null) {
+            cancellationSignal.setOnCancelListener(
+                    () -> removeUpdates(listener, null, packageName));
+        }
+        return true;
+    }
+
+    @Override
     public LocationTime getGnssTimeMillis() {
         synchronized (mLock) {
             Location location = mLastLocation.get(LocationManager.GPS_PROVIDER);
@@ -2528,7 +2593,7 @@
 
     @Override
     public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
-            String packageName, String listenerIdentifier) {
+            String packageName, String featureId, String listenerIdentifier) {
         Preconditions.checkNotNull(listenerIdentifier);
 
         if (request == null) request = DEFAULT_LOCATION_REQUEST;
@@ -2576,7 +2641,7 @@
             }
 
             mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
-                    uid, packageName, listenerIdentifier);
+                    uid, packageName, featureId, listenerIdentifier);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -2612,9 +2677,10 @@
     }
 
     @Override
-    public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName) {
+    public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
+            String featureId) {
         return mGnssManagerService == null ? false : mGnssManagerService.registerGnssStatusCallback(
-                listener, packageName);
+                listener, packageName, featureId);
     }
 
     @Override
@@ -2624,12 +2690,12 @@
 
     @Override
     public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
-            String packageName, String listenerIdentifier) {
+            String packageName, String featureId, String listenerIdentifier) {
         Preconditions.checkNotNull(listenerIdentifier);
 
         return mGnssManagerService == null ? false
-                : mGnssManagerService.addGnssMeasurementsListener(listener, packageName,
-                        listenerIdentifier);
+                : mGnssManagerService.addGnssMeasurementsListener(listener, packageName, featureId,
+                       listenerIdentifier);
     }
 
     @Override
@@ -2657,12 +2723,12 @@
 
     @Override
     public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
-            String packageName, String listenerIdentifier) {
+            String packageName, String featureId, String listenerIdentifier) {
         Preconditions.checkNotNull(listenerIdentifier);
 
         return mGnssManagerService == null ? false
                 : mGnssManagerService.addGnssNavigationMessageListener(listener, packageName,
-                        listenerIdentifier);
+                        featureId, listenerIdentifier);
     }
 
     @Override
@@ -2836,9 +2902,9 @@
 
         // Check whether sufficient time has passed
         long minTime = record.mRealRequest.getFastestInterval();
-        long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
-                / NANOS_PER_MILLI;
-        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
+        long deltaMs = TimeUnit.NANOSECONDS.toMillis(
+                loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
+        if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
             return false;
         }
 
@@ -2893,9 +2959,9 @@
                 mLastLocationCoarseInterval.put(provider.getName(), lastLocationCoarseInterval);
             }
         }
-        long timeDiffNanos = location.getElapsedRealtimeNanos()
-                - lastLocationCoarseInterval.getElapsedRealtimeNanos();
-        if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
+        long timeDeltaMs = TimeUnit.NANOSECONDS.toMillis(location.getElapsedRealtimeNanos()
+                - lastLocationCoarseInterval.getElapsedRealtimeNanos());
+        if (timeDeltaMs > LocationFudger.FASTEST_INTERVAL_MS) {
             lastLocationCoarseInterval.set(location);
         }
         // Don't ever return a coarse location that is more recent than the allowed update
@@ -2968,6 +3034,7 @@
                             receiver.mCallerIdentity.mPid,
                             receiver.mCallerIdentity.mUid,
                             receiver.mCallerIdentity.mPackageName,
+                            receiver.mCallerIdentity.mFeatureId,
                             receiver.mAllowedResolutionLevel,
                             "Location sent to " + receiver.mCallerIdentity.mListenerIdentifier)) {
                         if (D) {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index a502ff2..83ad4e7 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -104,6 +104,7 @@
             "android.hardware.audio@2.0::IDevicesFactory",
             "android.hardware.audio@4.0::IDevicesFactory",
             "android.hardware.audio@5.0::IDevicesFactory",
+            "android.hardware.audio@6.0::IDevicesFactory",
             "android.hardware.biometrics.face@1.0::IBiometricsFace",
             "android.hardware.bluetooth@1.0::IBluetoothHci",
             "android.hardware.camera.provider@2.4::ICameraProvider",
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 9209a21..eb77fea 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -569,7 +569,8 @@
                         r.lastActivity);
             }
             mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
-                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, true);
+                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null,
+                    true);
         }
 
         final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -1394,7 +1395,7 @@
                         mAm.mAppOpsService.startOperation(
                                 AppOpsManager.getToken(mAm.mAppOpsService),
                                 AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
-                                true);
+                                null, true);
                         StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                                 r.appInfo.uid, r.shortInstanceName,
                                 StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
@@ -1427,7 +1428,8 @@
                     // we have cleared the flag so can now drop it.
                     mAm.mAppOpsService.finishOperation(
                             AppOpsManager.getToken(mAm.mAppOpsService),
-                            AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                            AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
+                            null);
                 }
             }
         } else {
@@ -1444,7 +1446,7 @@
                 }
                 mAm.mAppOpsService.finishOperation(
                         AppOpsManager.getToken(mAm.mAppOpsService),
-                        AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                        AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
                 StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                         r.appInfo.uid, r.shortInstanceName,
                         StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
@@ -1819,7 +1821,7 @@
                                 || (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP
                                         && (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0),
                         b.client);
-                mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
+                mAm.updateOomAdjLocked(s.app, OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
             }
 
             if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
@@ -2701,7 +2703,7 @@
         bumpServiceExecutingLocked(r, execInFg, "create");
         mAm.updateLruProcessLocked(app, false, null);
         updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
-        mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
+        mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
 
         boolean created = false;
         try {
@@ -2981,7 +2983,7 @@
                         r.lastActivity);
             }
             mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
-                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
             mAm.mHandler.removeMessages(
                     ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
             if (r.app != null) {
@@ -3039,7 +3041,7 @@
             }
             mAm.mAppOpsService.finishOperation(
                     AppOpsManager.getToken(mAm.mAppOpsService),
-                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
+                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
             StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid,
                     r.shortInstanceName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
             mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 7fea5fc..9085d18 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -282,6 +282,19 @@
     // memory trimming.
     public int CUR_TRIM_CACHED_PROCESSES;
 
+    @SuppressWarnings("unused")
+    private static final int OOMADJ_UPDATE_POLICY_SLOW = 0;
+    private static final int OOMADJ_UPDATE_POLICY_QUICK = 1;
+    private static final int DEFAULT_OOMADJ_UPDATE_POLICY = OOMADJ_UPDATE_POLICY_QUICK;
+
+    private static final String KEY_OOMADJ_UPDATE_POLICY = "oomadj_update_policy";
+
+    // Indicate if the oom adjuster should take the quick path to update the oom adj scores,
+    // in which no futher actions will be performed if there are no significant adj/proc state
+    // changes for the specific process; otherwise, use the traditonal slow path which would
+    // keep updating all processes in the LRU list.
+    public boolean OOMADJ_UPDATE_QUICK = DEFAULT_OOMADJ_UPDATE_POLICY == OOMADJ_UPDATE_POLICY_QUICK;
+
     private static final long MIN_AUTOMATIC_HEAP_DUMP_PSS_THRESHOLD_BYTES = 100 * 1024; // 100 KB
 
     private final boolean mSystemServerAutomaticHeapDumpEnabled;
@@ -316,6 +329,9 @@
                             case KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED:
                                 updateBackgroundActivityStarts();
                                 break;
+                            case KEY_OOMADJ_UPDATE_POLICY:
+                                updateOomAdjUpdatePolicy();
+                                break;
                             default:
                                 break;
                         }
@@ -354,6 +370,7 @@
         updateMaxCachedProcesses();
         updateActivityStartsLoggingEnabled();
         updateBackgroundActivityStarts();
+        updateOomAdjUpdatePolicy();
     }
 
     public void setOverrideMaxCachedProcesses(int value) {
@@ -472,6 +489,14 @@
                 /*defaultValue*/ false);
     }
 
+    private void updateOomAdjUpdatePolicy() {
+        OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_OOMADJ_UPDATE_POLICY,
+                /* defaultValue */ DEFAULT_OOMADJ_UPDATE_POLICY)
+                == OOMADJ_UPDATE_POLICY_QUICK;
+    }
+
     private void updateEnableAutomaticSystemServerHeapDumps() {
         if (!mSystemServerAutomaticHeapDumpEnabled) {
             Slog.wtf(TAG,
@@ -587,5 +612,6 @@
         pw.print("  CUR_MAX_EMPTY_PROCESSES="); pw.println(CUR_MAX_EMPTY_PROCESSES);
         pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
         pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
+        pw.print("  OOMADJ_UPDATE_QUICK="); pw.println(OOMADJ_UPDATE_QUICK);
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 55cd933..11cfe12 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -42,8 +42,6 @@
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.os.FactoryTest.FACTORY_TEST_OFF;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
@@ -283,7 +281,6 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.EventLog;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.PrintWriterPrinter;
@@ -381,7 +378,6 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -424,7 +420,7 @@
     private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
     static final String TAG_LRU = TAG + POSTFIX_LRU;
     private static final String TAG_MU = TAG + POSTFIX_MU;
-    private static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
+    static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
     static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ;
     private static final String TAG_POWER = TAG + POSTFIX_POWER;
     static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
@@ -507,10 +503,6 @@
     static final int PERSISTENT_MASK =
             ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
 
-    // Intent sent when remote bugreport collection has been completed
-    private static final String INTENT_REMOTE_BUGREPORT_FINISHED =
-            "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
-
     // If set, we will push process association information in to procstats.
     static final boolean TRACK_PROCSTATS_ASSOCIATIONS = true;
 
@@ -534,27 +526,10 @@
      */
     private static final int BINDER_PROXY_LOW_WATERMARK = 5500;
 
-    /**
-     * State indicating that there is no need for any blocking for network.
-     */
-    @VisibleForTesting
-    static final int NETWORK_STATE_NO_CHANGE = 0;
-
-    /**
-     * State indicating that the main thread needs to be informed about the network wait.
-     */
-    @VisibleForTesting
-    static final int NETWORK_STATE_BLOCK = 1;
-
-    /**
-     * State indicating that any threads waiting for network state to get updated can be unblocked.
-     */
-    @VisibleForTesting
-    static final int NETWORK_STATE_UNBLOCK = 2;
-
     // Max character limit for a notification title. If the notification title is larger than this
     // the notification will not be legible to the user.
     private static final int MAX_BUGREPORT_TITLE_SIZE = 50;
+    private static final int MAX_BUGREPORT_DESCRIPTION_SIZE = 150;
 
     private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
     private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
@@ -1364,7 +1339,7 @@
     String mTrackAllocationApp = null;
     String mNativeDebuggingApp = null;
 
-    private final Injector mInjector;
+    final Injector mInjector;
 
     static final class ProcessChangeItem {
         static final int CHANGE_ACTIVITIES = 1<<0;
@@ -3154,7 +3129,7 @@
 
     private boolean hasUsageStatsPermission(String callingPackage) {
         final int mode = mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS,
-                Binder.getCallingUid(), callingPackage);
+                Binder.getCallingUid(), callingPackage, null);
         if (mode == AppOpsManager.MODE_DEFAULT) {
             return checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
                     == PackageManager.PERMISSION_GRANTED;
@@ -5175,7 +5150,7 @@
         }
 
         if (!didSomething) {
-            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
+            updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
             checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
         }
 
@@ -5690,6 +5665,7 @@
 
     void importanceTokenDied(ImportanceToken token) {
         synchronized (ActivityManagerService.this) {
+            ProcessRecord pr = null;
             synchronized (mPidsSelfLocked) {
                 ImportanceToken cur
                     = mImportantProcesses.get(token.pid);
@@ -5697,14 +5673,14 @@
                     return;
                 }
                 mImportantProcesses.remove(token.pid);
-                ProcessRecord pr = mPidsSelfLocked.get(token.pid);
+                pr = mPidsSelfLocked.get(token.pid);
                 if (pr == null) {
                     return;
                 }
                 pr.forcingToImportant = null;
                 updateProcessForegroundLocked(pr, false, 0, false);
             }
-            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+            updateOomAdjLocked(pr, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
         }
     }
 
@@ -5715,8 +5691,9 @@
         synchronized(this) {
             boolean changed = false;
 
+            ProcessRecord pr = null;
             synchronized (mPidsSelfLocked) {
-                ProcessRecord pr = mPidsSelfLocked.get(pid);
+                pr = mPidsSelfLocked.get(pid);
                 if (pr == null && isForeground) {
                     Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
                     return;
@@ -5750,7 +5727,7 @@
             }
 
             if (changed) {
-                updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+                updateOomAdjLocked(pr, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
             }
         }
     }
@@ -5856,8 +5833,9 @@
 
         @Override
         public int noteOp(String op, int uid, String packageName) {
+            // TODO moltmann: Allow to specify featureId
             return mActivityManagerService.mAppOpsService
-                    .noteOperation(AppOpsManager.strOpToOp(op), uid, packageName);
+                    .noteOperation(AppOpsManager.strOpToOp(op), uid, packageName, null);
         }
 
         @Override
@@ -6009,7 +5987,7 @@
         }
         // ...and legacy apps get an AppOp check
         int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
-                uid, packageName);
+                uid, packageName, null);
         if (DEBUG_BACKGROUND_CHECK) {
             Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
         }
@@ -7894,7 +7872,7 @@
                     new HostingRecord("added application",
                             customProcess != null ? customProcess : info.processName));
             mProcessList.updateLruProcessLocked(app, false, null);
-            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
+            updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
         }
 
         // This package really, really can not be stopped.
@@ -8251,24 +8229,18 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a bugreport using bug report API ({@code BugreportManager}) with no pre-set
+     * title and description
      */
-    // TODO(b/137825297): Remove deprecated annotation and rephrase comments for all
-    // requestBugreport functions below.
-    @Deprecated
     @Override
-    public void requestBugReport(int bugreportType) {
+    public void requestBugReport(@BugreportParams.BugreportMode int bugreportType) {
         requestBugReportWithDescription(null, null, bugreportType);
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a bugreport using bug report API ({@code BugreportManager}) which gets
+     * triggered by sending a broadcast to Shell.
      */
-    @Deprecated
     @Override
     public void requestBugReportWithDescription(@Nullable String shareTitle,
             @Nullable String shareDescription, int bugreportType) {
@@ -8303,60 +8275,45 @@
 
         if (!TextUtils.isEmpty(shareTitle)) {
             if (shareTitle.length() > MAX_BUGREPORT_TITLE_SIZE) {
-                String errorStr = "shareTitle should be less than " +
-                        MAX_BUGREPORT_TITLE_SIZE + " characters";
+                String errorStr = "shareTitle should be less than "
+                        + MAX_BUGREPORT_TITLE_SIZE + " characters";
                 throw new IllegalArgumentException(errorStr);
             }
             if (!TextUtils.isEmpty(shareDescription)) {
-                int length = shareDescription.getBytes(StandardCharsets.UTF_8).length;
-                if (length > SystemProperties.PROP_VALUE_MAX) {
-                    String errorStr = "shareTitle should be less than " +
-                            SystemProperties.PROP_VALUE_MAX + " bytes";
+                if (shareDescription.length() > MAX_BUGREPORT_DESCRIPTION_SIZE) {
+                    String errorStr = "shareDescription should be less than "
+                            + MAX_BUGREPORT_DESCRIPTION_SIZE + " characters";
                     throw new IllegalArgumentException(errorStr);
-                } else {
-                    SystemProperties.set("dumpstate.options.description", shareDescription);
                 }
             }
-            SystemProperties.set("dumpstate.options.title", shareTitle);
             Slog.d(TAG, "Bugreport notification title " + shareTitle
                     + " description " + shareDescription);
         }
-        final boolean useApi = FeatureFlagUtils.isEnabled(mContext,
-                FeatureFlagUtils.USE_BUGREPORT_API);
-
-        if (useApi) {
-            // Create intent to trigger Bugreport API via Shell
-            Intent triggerShellBugreport = new Intent();
-            triggerShellBugreport.setAction(INTENT_BUGREPORT_REQUESTED);
-            triggerShellBugreport.setPackage(SHELL_APP_PACKAGE);
-            triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType);
-            triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-            if (shareTitle != null) {
-                triggerShellBugreport.putExtra(EXTRA_TITLE, shareTitle);
-            }
-            if (shareDescription != null) {
-                triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription);
-            }
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                // Send broadcast to shell to trigger bugreport using Bugreport API
-                mContext.sendBroadcast(triggerShellBugreport);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        } else {
-            SystemProperties.set("dumpstate.options", type);
-            SystemProperties.set("ctl.start", "bugreport");
+        // Create intent to trigger Bugreport API via Shell
+        Intent triggerShellBugreport = new Intent();
+        triggerShellBugreport.setAction(INTENT_BUGREPORT_REQUESTED);
+        triggerShellBugreport.setPackage(SHELL_APP_PACKAGE);
+        triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType);
+        triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        if (shareTitle != null) {
+            triggerShellBugreport.putExtra(EXTRA_TITLE, shareTitle);
+        }
+        if (shareDescription != null) {
+            triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription);
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            // Send broadcast to shell to trigger bugreport using Bugreport API
+            mContext.sendBroadcast(triggerShellBugreport);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a telephony bugreport with title and description
      */
-    @Deprecated
     @Override
     public void requestTelephonyBugReport(String shareTitle, String shareDescription) {
         requestBugReportWithDescription(shareTitle, shareDescription,
@@ -8364,11 +8321,8 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon start
-     * using bug report API (which will be restricted to a few, pre-defined apps).
-     * No new code should be calling it.
+     * Takes a minimal bugreport of Wifi-related state with pre-set title and description
      */
-    @Deprecated
     @Override
     public void requestWifiBugReport(String shareTitle, String shareDescription) {
         requestBugReportWithDescription(shareTitle, shareDescription,
@@ -14970,12 +14924,10 @@
             HashSet<ComponentName> singleUserReceivers = null;
             boolean scannedFirstReceivers = false;
             for (int user : users) {
-                // Skip users that have Shell restrictions, with exception of always permitted
-                // Shell broadcasts
+                // Skip users that have Shell restrictions
                 if (callingUid == SHELL_UID
                         && mUserController.hasUserRestriction(
-                                UserManager.DISALLOW_DEBUGGING_FEATURES, user)
-                        && !isPermittedShellBroadcast(intent)) {
+                                UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
                     continue;
                 }
                 List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
@@ -15042,11 +14994,6 @@
         return receivers;
     }
 
-    private boolean isPermittedShellBroadcast(Intent intent) {
-        // remote bugreport should always be allowed to be taken
-        return INTENT_REMOTE_BUGREPORT_FINISHED.equals(intent.getAction());
-    }
-
     private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,
             String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {
         if ((intent.getFlags() & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
@@ -17035,7 +16982,7 @@
             item.foregroundServiceTypes = fgServiceTypes;
 
             if (oomAdj) {
-                updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+                updateOomAdjLocked(proc, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
             }
         }
     }
@@ -17290,6 +17237,16 @@
         mOomAdjuster.updateOomAdjLocked(oomAdjReason);
     }
 
+    /*
+     * Update OomAdj for a specific process and its reachable processes.
+     * @param app The process to update
+     * @param oomAdjReason
+     */
+    @GuardedBy("this")
+    final void updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+        mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
+    }
+
     @Override
     public void makePackageIdle(String packageName, int userId) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
@@ -17356,115 +17313,6 @@
         }
     }
 
-    /**
-     * Checks if any uid is coming from background to foreground or vice versa and if so, increments
-     * the {@link UidRecord#curProcStateSeq} corresponding to that uid using global seq counter
-     * {@link ProcessList#mProcStateSeqCounter} and notifies the app if it needs to block.
-     */
-    @VisibleForTesting
-    @GuardedBy("this")
-    void incrementProcStateSeqAndNotifyAppsLocked() {
-        if (mWaitForNetworkTimeoutMs <= 0) {
-            return;
-        }
-        // Used for identifying which uids need to block for network.
-        ArrayList<Integer> blockingUids = null;
-        for (int i = mProcessList.mActiveUids.size() - 1; i >= 0; --i) {
-            final UidRecord uidRec = mProcessList.mActiveUids.valueAt(i);
-            // If the network is not restricted for uid, then nothing to do here.
-            if (!mInjector.isNetworkRestrictedForUid(uidRec.uid)) {
-                continue;
-            }
-            if (!UserHandle.isApp(uidRec.uid) || !uidRec.hasInternetPermission) {
-                continue;
-            }
-            // If process state is not changed, then there's nothing to do.
-            if (uidRec.setProcState == uidRec.getCurProcState()) {
-                continue;
-            }
-            final int blockState = getBlockStateForUid(uidRec);
-            // No need to inform the app when the blockState is NETWORK_STATE_NO_CHANGE as
-            // there's nothing the app needs to do in this scenario.
-            if (blockState == NETWORK_STATE_NO_CHANGE) {
-                continue;
-            }
-            synchronized (uidRec.networkStateLock) {
-                uidRec.curProcStateSeq = ++mProcessList.mProcStateSeqCounter; // TODO: use method
-                if (blockState == NETWORK_STATE_BLOCK) {
-                    if (blockingUids == null) {
-                        blockingUids = new ArrayList<>();
-                    }
-                    blockingUids.add(uidRec.uid);
-                } else {
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
-                                + " threads for uid: " + uidRec);
-                    }
-                    if (uidRec.waitingForNetwork) {
-                        uidRec.networkStateLock.notifyAll();
-                    }
-                }
-            }
-        }
-
-        // There are no uids that need to block, so nothing more to do.
-        if (blockingUids == null) {
-            return;
-        }
-
-        for (int i = mProcessList.mLruProcesses.size() - 1; i >= 0; --i) {
-            final ProcessRecord app = mProcessList.mLruProcesses.get(i);
-            if (!blockingUids.contains(app.uid)) {
-                continue;
-            }
-            if (!app.killedByAm && app.thread != null) {
-                final UidRecord uidRec = mProcessList.getUidRecordLocked(app.uid);
-                try {
-                    if (DEBUG_NETWORK) {
-                        Slog.d(TAG_NETWORK, "Informing app thread that it needs to block: "
-                                + uidRec);
-                    }
-                    if (uidRec != null) {
-                        app.thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
-                    }
-                } catch (RemoteException ignored) {
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks if the uid is coming from background to foreground or vice versa and returns
-     * appropriate block state based on this.
-     *
-     * @return blockState based on whether the uid is coming from background to foreground or
-     *         vice versa. If bg->fg or fg->bg, then {@link #NETWORK_STATE_BLOCK} or
-     *         {@link #NETWORK_STATE_UNBLOCK} respectively, otherwise
-     *         {@link #NETWORK_STATE_NO_CHANGE}.
-     */
-    @VisibleForTesting
-    int getBlockStateForUid(UidRecord uidRec) {
-        // Denotes whether uid's process state is currently allowed network access.
-        final boolean isAllowed =
-                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
-                || isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
-        // Denotes whether uid's process state was previously allowed network access.
-        final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
-                || isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
-
-        // When the uid is coming to foreground, AMS should inform the app thread that it should
-        // block for the network rules to get updated before launching an activity.
-        if (!wasAllowed && isAllowed) {
-            return NETWORK_STATE_BLOCK;
-        }
-        // When the uid is going to background, AMS should inform the app thread that if an
-        // activity launch is blocked for the network rules to get updated, it should be unblocked.
-        if (wasAllowed && !isAllowed) {
-            return NETWORK_STATE_UNBLOCK;
-        }
-        return NETWORK_STATE_NO_CHANGE;
-    }
-
     final void runInBackgroundDisabled(int uid) {
         synchronized (this) {
             UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
@@ -19314,18 +19162,19 @@
         }
 
         @Override
-        public int noteOperation(int code, int uid, String packageName,
-                TriFunction<Integer, Integer, String, Integer> superImpl) {
+        public int noteOperation(int code, int uid, @Nullable String packageName,
+                @Nullable String featureId,
+                @NonNull QuadFunction<Integer, Integer, String, String, Integer> superImpl) {
             if (uid == mTargetUid && isTargetOp(code)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return mAppOpsService.noteProxyOperation(code, Process.SHELL_UID,
-                            "com.android.shell", uid, packageName);
+                            "com.android.shell", null, uid, packageName, featureId);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
             }
-            return superImpl.apply(code, uid, packageName);
+            return superImpl.apply(code, uid, packageName, featureId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 59c2326..1d03b36 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -309,7 +309,7 @@
         app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
         mService.mProcessList.updateLruProcessLocked(app, false, null);
         if (!skipOomAdj) {
-            mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+            mService.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
         }
 
         // Tell the application to launch this receiver.
@@ -647,9 +647,10 @@
                 skip = true;
             } else {
                 final int opCode = AppOpsManager.permissionToOpCode(filter.requiredPermission);
+                // TODO moltmann: Set featureId from caller
                 if (opCode != AppOpsManager.OP_NONE
                         && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
-                                r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+                                r.callerPackage, null) != AppOpsManager.MODE_ALLOWED) {
                     Slog.w(TAG, "Appop Denial: broadcasting "
                             + r.intent.toString()
                             + " from " + r.callerPackage + " (pid="
@@ -679,9 +680,10 @@
                     break;
                 }
                 int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
+                // TODO moltmann: Set componentId from caller
                 if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
                         && mService.mAppOpsService.noteOperation(appOp,
-                        filter.receiverList.uid, filter.packageName)
+                        filter.receiverList.uid, filter.packageName, null)
                         != AppOpsManager.MODE_ALLOWED) {
                     Slog.w(TAG, "Appop Denial: receiving "
                             + r.intent.toString()
@@ -711,9 +713,10 @@
                 skip = true;
             }
         }
+        // TODO moltmann: Set componentId from caller
         if (!skip && r.appOp != AppOpsManager.OP_NONE
                 && mService.mAppOpsService.noteOperation(r.appOp,
-                filter.receiverList.uid, filter.packageName)
+                filter.receiverList.uid, filter.packageName, null)
                 != AppOpsManager.MODE_ALLOWED) {
             Slog.w(TAG, "Appop Denial: receiving "
                     + r.intent.toString()
@@ -1367,9 +1370,10 @@
             skip = true;
         } else if (!skip && info.activityInfo.permission != null) {
             final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
+            // TODO moltmann: Set componentId from caller
             if (opCode != AppOpsManager.OP_NONE
                     && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
-                            r.callerPackage) != AppOpsManager.MODE_ALLOWED) {
+                            r.callerPackage, null) != AppOpsManager.MODE_ALLOWED) {
                 Slog.w(TAG, "Appop Denial: broadcasting "
                         + r.intent.toString()
                         + " from " + r.callerPackage + " (pid="
@@ -1405,9 +1409,10 @@
                     break;
                 }
                 int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
+                // TODO moltmann: Set componentId from caller
                 if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
                         && mService.mAppOpsService.noteOperation(appOp,
-                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null)
                         != AppOpsManager.MODE_ALLOWED) {
                     Slog.w(TAG, "Appop Denial: receiving "
                             + r.intent + " to "
@@ -1421,9 +1426,10 @@
                 }
             }
         }
+        // TODO moltmann: Set componentId from caller
         if (!skip && r.appOp != AppOpsManager.OP_NONE
                 && mService.mAppOpsService.noteOperation(r.appOp,
-                info.activityInfo.applicationInfo.uid, info.activityInfo.packageName)
+                info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null)
                 != AppOpsManager.MODE_ALLOWED) {
             Slog.w(TAG, "Appop Denial: receiving "
                     + r.intent + " to "
diff --git a/services/core/java/com/android/server/am/OomAdjProfiler.java b/services/core/java/com/android/server/am/OomAdjProfiler.java
index 7e381840..0869114 100644
--- a/services/core/java/com/android/server/am/OomAdjProfiler.java
+++ b/services/core/java/com/android/server/am/OomAdjProfiler.java
@@ -45,7 +45,7 @@
     private boolean mLastScheduledScreenOff;
 
     @GuardedBy("this")
-    private long mOomAdjStartTimeMs;
+    private long mOomAdjStartTimeUs;
     @GuardedBy("this")
     private boolean mOomAdjStarted;
 
@@ -65,6 +65,11 @@
     @GuardedBy("this")
     final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
 
+    @GuardedBy("this")
+    private long mTotalOomAdjRunTimeUs;
+    @GuardedBy("this")
+    private int mTotalOomAdjCalls;
+
     void batteryPowerChanged(boolean onBattery) {
         synchronized (this) {
             scheduleSystemServerCpuTimeUpdate();
@@ -81,7 +86,7 @@
 
     void oomAdjStarted() {
         synchronized (this) {
-            mOomAdjStartTimeMs = SystemClock.currentThreadTimeMillis();
+            mOomAdjStartTimeUs = SystemClock.currentThreadTimeMicro();
             mOomAdjStarted = true;
         }
     }
@@ -91,7 +96,10 @@
             if (!mOomAdjStarted) {
                 return;
             }
-            mOomAdjRunTime.addCpuTimeMs(SystemClock.currentThreadTimeMillis() - mOomAdjStartTimeMs);
+            long elapsedUs = SystemClock.currentThreadTimeMicro() - mOomAdjStartTimeUs;
+            mOomAdjRunTime.addCpuTimeUs(elapsedUs);
+            mTotalOomAdjRunTimeUs += elapsedUs;
+            mTotalOomAdjCalls++;
         }
     }
 
@@ -169,32 +177,50 @@
                 pw.print("oom_adj=");
                 pw.println(oomAdjRunTimes[i]);
             }
+            if (mTotalOomAdjCalls != 0) {
+                pw.println("System server total oomAdj runtimes (us) since boot:");
+                pw.print("  cpu time spent=");
+                pw.print(mTotalOomAdjRunTimeUs);
+                pw.print("  number of calls=");
+                pw.print(mTotalOomAdjCalls);
+                pw.print("  average=");
+                pw.println(mTotalOomAdjRunTimeUs / mTotalOomAdjCalls);
+            }
         }
     }
 
     private class CpuTimes {
-        private long mOnBatteryTimeMs;
-        private long mOnBatteryScreenOffTimeMs;
+        private long mOnBatteryTimeUs;
+        private long mOnBatteryScreenOffTimeUs;
 
         public void addCpuTimeMs(long cpuTimeMs) {
-            addCpuTimeMs(cpuTimeMs, mOnBattery, mScreenOff);
+            addCpuTimeUs(cpuTimeMs * 1000, mOnBattery, mScreenOff);
         }
 
         public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
+            addCpuTimeUs(cpuTimeMs * 1000, onBattery, screenOff);
+        }
+
+        public void addCpuTimeUs(long cpuTimeUs) {
+            addCpuTimeUs(cpuTimeUs, mOnBattery, mScreenOff);
+        }
+
+        public void addCpuTimeUs(long cpuTimeUs, boolean onBattery, boolean screenOff) {
             if (onBattery) {
-                mOnBatteryTimeMs += cpuTimeMs;
+                mOnBatteryTimeUs += cpuTimeUs;
                 if (screenOff) {
-                    mOnBatteryScreenOffTimeMs += cpuTimeMs;
+                    mOnBatteryScreenOffTimeUs += cpuTimeUs;
                 }
             }
         }
 
         public boolean isEmpty() {
-            return mOnBatteryTimeMs == 0 && mOnBatteryScreenOffTimeMs == 0;
+            return mOnBatteryTimeUs == 0 && mOnBatteryScreenOffTimeUs == 0;
         }
 
         public String toString() {
-            return "[" + mOnBatteryTimeMs + "," + mOnBatteryScreenOffTimeMs + "]";
+            return "[" + (mOnBatteryTimeUs / 1000) + ","
+                    + (mOnBatteryScreenOffTimeUs / 1000) + "]";
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index bb214bd..78a9efc 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -19,7 +19,9 @@
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
@@ -62,6 +64,7 @@
 import android.app.ActivityManager;
 import android.app.usage.UsageEvents;
 import android.content.Context;
+import android.content.pm.ServiceInfo;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
@@ -85,6 +88,7 @@
 import com.android.server.wm.WindowProcessController;
 
 import java.io.PrintWriter;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -162,6 +166,12 @@
     private final ActivityManagerService mService;
     private final ProcessList mProcessList;
 
+    private final int mNumSlots;
+    private ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>();
+    private ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>();
+    private ActiveUids mTmpUidRecords;
+    private ArrayDeque<ProcessRecord> mTmpQueue;
+
     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
         this(service, processList, activeUids, createAdjusterThread());
     }
@@ -204,6 +214,10 @@
             }
             return true;
         });
+        mTmpUidRecords = new ActiveUids(service, false);
+        mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1);
+        mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1)
+                / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
     }
 
     void initSettings() {
@@ -221,6 +235,9 @@
     @GuardedBy("mService")
     boolean updateOomAdjLocked(ProcessRecord app, boolean oomAdjAll,
             String oomAdjReason) {
+        if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
+            return updateOomAdjLocked(app, oomAdjReason);
+        }
         final ProcessRecord TOP_APP = mService.getTopAppLocked();
         final boolean wasCached = app.cached;
 
@@ -250,26 +267,189 @@
             return false;
         }
 
-        computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false);
+        app.resetCachedInfo();
+        UidRecord uidRec = app.uidRecord;
+        if (uidRec != null) {
+            if (DEBUG_UID_OBSERVERS) {
+                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
+            }
+            uidRec.reset();
+        }
 
-        return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
+        computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now, false, true);
+
+        boolean success = applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
+
+        if (uidRec != null) {
+            updateAppUidRecLocked(app);
+            // If this proc state is changed, need to update its uid record here
+            if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
+                    && (uidRec.setProcState != uidRec.getCurProcState()
+                    || uidRec.setWhitelist != uidRec.curWhitelist)) {
+                ActiveUids uids = mTmpUidRecords;
+                uids.clear();
+                uids.put(uidRec.uid, uidRec);
+                updateUidsLocked(uids, now);
+                mProcessList.incrementProcStateSeqAndNotifyAppsLocked(uids);
+            }
+        }
+
+        return success;
     }
 
+    /**
+     * Update OomAdj for all processes in LRU list
+     */
     @GuardedBy("mService")
     void updateOomAdjLocked(String oomAdjReason) {
+        final ProcessRecord topApp = mService.getTopAppLocked();
+        updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true);
+    }
+
+    /**
+     * Update OomAdj for specific process and its reachable processes (with direction/indirect
+     * bindings from this process); Note its clients' proc state won't be re-evaluated if this proc
+     * is hosting any service/content provider.
+     *
+     * @param app The process to update, or null to update all processes
+     * @param oomAdjReason
+     */
+    @GuardedBy("mService")
+    boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+        if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
+            updateOomAdjLocked(oomAdjReason);
+            return true;
+        }
+
+        final ProcessRecord topApp = mService.getTopAppLocked();
+
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
         mService.mOomAdjProfiler.oomAdjStarted();
-        final ProcessRecord TOP_APP = mService.getTopAppLocked();
+        mAdjSeq++;
+
+        // Firstly, try to see if the importance of itself gets changed
+        final boolean wasCached = app.cached;
+        final int oldAdj = app.getCurRawAdj();
+        final int cachedAdj = oldAdj >= ProcessList.CACHED_APP_MIN_ADJ
+                ? oldAdj : ProcessList.UNKNOWN_ADJ;
+        final boolean wasBackground = ActivityManager.isProcStateBackground(app.setProcState);
+        app.containsCycle = false;
+        app.procStateChanged = false;
+        app.resetCachedInfo();
+        boolean success = updateOomAdjLocked(app, cachedAdj, topApp, false,
+                SystemClock.uptimeMillis());
+        if (!success || (wasCached == app.cached && oldAdj != ProcessList.INVALID_ADJ
+                && wasBackground == ActivityManager.isProcStateBackground(app.setProcState))) {
+            // Okay, it's unchanged, it won't impact any service it binds to, we're done here.
+            if (DEBUG_OOM_ADJ) {
+                Slog.i(TAG_OOM_ADJ, "No oomadj changes for " + app);
+            }
+            mService.mOomAdjProfiler.oomAdjEnded();
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+            return success;
+        }
+
+        // Next to find out all its reachable processes
+        ArrayList<ProcessRecord> processes = mTmpProcessList;
+        ActiveUids uids = mTmpUidRecords;
+        ArrayDeque<ProcessRecord> queue = mTmpQueue;
+
+        processes.clear();
+        uids.clear();
+        queue.clear();
+
+        // borrow the "containsCycle" flag to mark it being scanned
+        app.containsCycle = true;
+        for (ProcessRecord pr = app; pr != null; pr = queue.poll()) {
+            if (pr != app) {
+                processes.add(pr);
+            }
+            if (pr.uidRecord != null) {
+                uids.put(pr.uidRecord.uid, pr.uidRecord);
+            }
+            for (int i = pr.connections.size() - 1; i >= 0; i--) {
+                ConnectionRecord cr = pr.connections.valueAt(i);
+                ProcessRecord service = (cr.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
+                        ? cr.binding.service.isolatedProc : cr.binding.service.app;
+                if (service == null || service.containsCycle) {
+                    continue;
+                }
+                if ((cr.flags & (Context.BIND_WAIVE_PRIORITY
+                        | Context.BIND_TREAT_LIKE_ACTIVITY
+                        | Context.BIND_ADJUST_WITH_ACTIVITY))
+                        == Context.BIND_WAIVE_PRIORITY) {
+                    continue;
+                }
+                queue.offer(service);
+                service.containsCycle = true;
+            }
+            for (int i = pr.conProviders.size() - 1; i >= 0; i--) {
+                ContentProviderConnection cpc = pr.conProviders.get(i);
+                ProcessRecord provider = cpc.provider.proc;
+                if (provider == null || provider.containsCycle) {
+                    continue;
+                }
+                queue.offer(provider);
+                provider.containsCycle = true;
+            }
+        }
+
+        // Reset the flag
+        app.containsCycle = false;
+        int size = processes.size();
+        if (size > 0) {
+            // Reverse the process list, since the updateOomAdjLockedInner scans from the end of it.
+            for (int l = 0, r = size - 1; l < r; l++, r--) {
+                ProcessRecord t = processes.get(l);
+                processes.set(l, processes.get(r));
+                processes.set(r, t);
+            }
+            mAdjSeq--;
+            // Update these reachable processes
+            updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, false);
+        }
+        mService.mOomAdjProfiler.oomAdjEnded();
+        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+        return true;
+    }
+
+    /**
+     * Update OomAdj for all processes within the given list (could be partial), or the whole LRU
+     * list if the given list is null; when it's partial update, each process's client proc won't
+     * get evaluated recursively here.
+     */
+    @GuardedBy("mService")
+    private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
+            ArrayList<ProcessRecord> processes, ActiveUids uids, boolean startProfiling) {
+        if (startProfiling) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+            mService.mOomAdjProfiler.oomAdjStarted();
+        }
         final long now = SystemClock.uptimeMillis();
         final long nowElapsed = SystemClock.elapsedRealtime();
         final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
-        final int N = mProcessList.getLruSizeLocked();
+        final boolean fullUpdate = processes == null;
+        ActiveUids activeUids = uids;
+        ArrayList<ProcessRecord> activeProcesses = fullUpdate ? mProcessList.mLruProcesses
+                : processes;
+        final int numProc = activeProcesses.size();
+
+        if (activeUids == null) {
+            final int numUids = mActiveUids.size();
+            activeUids = mTmpUidRecords;
+            activeUids.clear();
+            for (int i = 0; i < numUids; i++) {
+                UidRecord r = mActiveUids.valueAt(i);
+                activeUids.put(r.uid, r);
+            }
+        }
 
         // Reset state in all uid records.
-        for (int  i = mActiveUids.size() - 1; i >= 0; i--) {
-            final UidRecord uidRec = mActiveUids.valueAt(i);
-            if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
-                    "Starting update of " + uidRec);
+        for (int  i = activeUids.size() - 1; i >= 0; i--) {
+            final UidRecord uidRec = activeUids.valueAt(i);
+            if (DEBUG_UID_OBSERVERS) {
+                Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
+            }
             uidRec.reset();
         }
 
@@ -278,48 +458,112 @@
         }
 
         mAdjSeq++;
-        mNewNumServiceProcs = 0;
-        mNewNumAServiceProcs = 0;
-
-        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
-        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
-                - emptyProcessLimit;
-
-        // Let's determine how many processes we have running vs.
-        // how many slots we have for background processes; we may want
-        // to put multiple processes in a slot of there are enough of
-        // them.
-        final int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
-                - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2
-                / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
-        int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
-        if (numEmptyProcs > cachedProcessLimit) {
-            // If there are more empty processes than our limit on cached
-            // processes, then use the cached process limit for the factor.
-            // This ensures that the really old empty processes get pushed
-            // down to the bottom, so if we are running low on memory we will
-            // have a better chance at keeping around more cached processes
-            // instead of a gazillion empty processes.
-            numEmptyProcs = cachedProcessLimit;
+        if (fullUpdate) {
+            mNewNumServiceProcs = 0;
+            mNewNumAServiceProcs = 0;
         }
-        int emptyFactor = (numEmptyProcs + numSlots - 1) / numSlots;
-        if (emptyFactor < 1) emptyFactor = 1;
-        int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + numSlots - 1) : 1)
-                / numSlots;
-        if (cachedFactor < 1) cachedFactor = 1;
-        int stepCached = -1;
-        int stepEmpty = -1;
-        int numCached = 0;
-        int numCachedExtraGroup = 0;
-        int numEmpty = 0;
-        int numTrimming = 0;
-        int lastCachedGroup = 0;
-        int lastCachedGroupImportance = 0;
-        int lastCachedGroupUid = 0;
+
+        boolean retryCycles = false;
+
+        // need to reset cycle state before calling computeOomAdjLocked because of service conns
+        for (int i = numProc - 1; i >= 0; i--) {
+            ProcessRecord app = activeProcesses.get(i);
+            app.containsCycle = false;
+            app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
+            app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
+            app.resetCachedInfo();
+        }
+        for (int i = numProc - 1; i >= 0; i--) {
+            ProcessRecord app = activeProcesses.get(i);
+            if (!app.killedByAm && app.thread != null) {
+                app.procStateChanged = false;
+                computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
+                        fullUpdate); // It won't enter cycle if not computing clients.
+                // if any app encountered a cycle, we need to perform an additional loop later
+                retryCycles |= app.containsCycle;
+                // Keep the completedAdjSeq to up to date.
+                app.completedAdjSeq = mAdjSeq;
+            }
+        }
+
+        assignCachedAdjIfNecessary();
+
+        if (fullUpdate) { // There won't be cycles if we didn't compute clients above.
+            // Cycle strategy:
+            // - Retry computing any process that has encountered a cycle.
+            // - Continue retrying until no process was promoted.
+            // - Iterate from least important to most important.
+            int cycleCount = 0;
+            while (retryCycles && cycleCount < 10) {
+                cycleCount++;
+                retryCycles = false;
+
+                for (int i = 0; i < numProc; i++) {
+                    ProcessRecord app = activeProcesses.get(i);
+                    if (!app.killedByAm && app.thread != null && app.containsCycle) {
+                        app.adjSeq--;
+                        app.completedAdjSeq--;
+                    }
+                }
+
+                for (int i = 0; i < numProc; i++) {
+                    ProcessRecord app = activeProcesses.get(i);
+                    if (!app.killedByAm && app.thread != null && app.containsCycle) {
+                        if (computeOomAdjLocked(app, app.getCurRawAdj(), topApp, true, now,
+                                true, true)) {
+                            retryCycles = true;
+                        }
+                    }
+                }
+            }
+        }
 
         mNumNonCachedProcs = 0;
         mNumCachedHiddenProcs = 0;
 
+        boolean allChanged = updateAndTrimProcessLocked(now, nowElapsed, oldTime, activeUids);
+        mNumServiceProcs = mNewNumServiceProcs;
+
+        if (mService.mAlwaysFinishActivities) {
+            // Need to do this on its own message because the stack may not
+            // be in a consistent state at this point.
+            mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
+        }
+
+        if (allChanged) {
+            mService.requestPssAllProcsLocked(now, false,
+                    mService.mProcessStats.isMemFactorLowered());
+        }
+
+        updateUidsLocked(activeUids, nowElapsed);
+
+        if (mService.mProcessStats.shouldWriteNowLocked(now)) {
+            mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
+                    mService.mProcessStats));
+        }
+
+        // Run this after making sure all procstates are updated.
+        mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
+
+        if (DEBUG_OOM_ADJ) {
+            final long duration = SystemClock.uptimeMillis() - now;
+            if (false) {
+                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
+                        new RuntimeException("here").fillInStackTrace());
+            } else {
+                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
+            }
+        }
+        if (startProfiling) {
+            mService.mOomAdjProfiler.oomAdjEnded();
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+        }
+    }
+
+    private void assignCachedAdjIfNecessary() {
+        ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
+        final int numLru = lruList.size();
+
         // First update the OOM adjustment for each of the
         // application processes based on their current state.
         int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
@@ -328,136 +572,143 @@
         int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
         int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
 
-        boolean retryCycles = false;
-
-        // need to reset cycle state before calling computeOomAdjLocked because of service conns
-        for (int i = N - 1; i >= 0; i--) {
-            ProcessRecord app = mProcessList.mLruProcesses.get(i);
-            app.containsCycle = false;
-            app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
-            app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
+        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
+        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
+                - emptyProcessLimit;
+        // Let's determine how many processes we have running vs.
+        // how many slots we have for background processes; we may want
+        // to put multiple processes in a slot of there are enough of
+        // them.
+        int numEmptyProcs = numLru - mNumNonCachedProcs - mNumCachedHiddenProcs;
+        if (numEmptyProcs > cachedProcessLimit) {
+            // If there are more empty processes than our limit on cached
+            // processes, then use the cached process limit for the factor.
+            // This ensures that the really old empty processes get pushed
+            // down to the bottom, so if we are running low on memory we will
+            // have a better chance at keeping around more cached processes
+            // instead of a gazillion empty processes.
+            numEmptyProcs = cachedProcessLimit;
         }
-        for (int i = N - 1; i >= 0; i--) {
-            ProcessRecord app = mProcessList.mLruProcesses.get(i);
-            if (!app.killedByAm && app.thread != null) {
-                app.procStateChanged = false;
-                computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now, false);
+        int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + mNumSlots - 1) : 1)
+                / mNumSlots;
+        if (cachedFactor < 1) cachedFactor = 1;
 
-                // if any app encountered a cycle, we need to perform an additional loop later
-                retryCycles |= app.containsCycle;
+        int emptyFactor = (numEmptyProcs + mNumSlots - 1) / mNumSlots;
+        if (emptyFactor < 1) emptyFactor = 1;
 
-                // If we haven't yet assigned the final cached adj
-                // to the process, do that now.
-                if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
-                    switch (app.getCurProcState()) {
-                        case PROCESS_STATE_CACHED_ACTIVITY:
-                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
-                        case ActivityManager.PROCESS_STATE_CACHED_RECENT:
-                            // Figure out the next cached level, taking into account groups.
-                            boolean inGroup = false;
-                            if (app.connectionGroup != 0) {
-                                if (lastCachedGroupUid == app.uid
-                                        && lastCachedGroup == app.connectionGroup) {
-                                    // This is in the same group as the last process, just tweak
-                                    // adjustment by importance.
-                                    if (app.connectionImportance > lastCachedGroupImportance) {
-                                        lastCachedGroupImportance = app.connectionImportance;
-                                        if (curCachedAdj < nextCachedAdj
-                                                && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
-                                            curCachedImpAdj++;
-                                        }
-                                    }
-                                    inGroup = true;
-                                } else {
-                                    lastCachedGroupUid = app.uid;
-                                    lastCachedGroup = app.connectionGroup;
+        int stepCached = -1;
+        int stepEmpty = -1;
+        int lastCachedGroup = 0;
+        int lastCachedGroupImportance = 0;
+        int lastCachedGroupUid = 0;
+
+        for (int i = numLru - 1; i >= 0; i--) {
+            ProcessRecord app = lruList.get(i);
+            // If we haven't yet assigned the final cached adj
+            // to the process, do that now.
+            if (!app.killedByAm && app.thread != null && app.curAdj
+                    >= ProcessList.UNKNOWN_ADJ) {
+                switch (app.getCurProcState()) {
+                    case PROCESS_STATE_CACHED_ACTIVITY:
+                    case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
+                    case ActivityManager.PROCESS_STATE_CACHED_RECENT:
+                        // Figure out the next cached level, taking into account groups.
+                        boolean inGroup = false;
+                        if (app.connectionGroup != 0) {
+                            if (lastCachedGroupUid == app.uid
+                                    && lastCachedGroup == app.connectionGroup) {
+                                // This is in the same group as the last process, just tweak
+                                // adjustment by importance.
+                                if (app.connectionImportance > lastCachedGroupImportance) {
                                     lastCachedGroupImportance = app.connectionImportance;
-                                }
-                            }
-                            if (!inGroup && curCachedAdj != nextCachedAdj) {
-                                stepCached++;
-                                curCachedImpAdj = 0;
-                                if (stepCached >= cachedFactor) {
-                                    stepCached = 0;
-                                    curCachedAdj = nextCachedAdj;
-                                    nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
-                                    if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
-                                        nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
+                                    if (curCachedAdj < nextCachedAdj
+                                            && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
+                                        curCachedImpAdj++;
                                     }
                                 }
+                                inGroup = true;
+                            } else {
+                                lastCachedGroupUid = app.uid;
+                                lastCachedGroup = app.connectionGroup;
+                                lastCachedGroupImportance = app.connectionImportance;
                             }
-                            // This process is a cached process holding activities...
-                            // assign it the next cached value for that type, and then
-                            // step that cached level.
-                            app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
-                            app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
-                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
+                        }
+                        if (!inGroup && curCachedAdj != nextCachedAdj) {
+                            stepCached++;
+                            curCachedImpAdj = 0;
+                            if (stepCached >= cachedFactor) {
+                                stepCached = 0;
+                                curCachedAdj = nextCachedAdj;
+                                nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+                                if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+                                    nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
+                                }
+                            }
+                        }
+                        // This process is a cached process holding activities...
+                        // assign it the next cached value for that type, and then
+                        // step that cached level.
+                        app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
+                        app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
+                        if (DEBUG_LRU) {
+                            Slog.d(TAG_LRU, "Assigning activity LRU #" + i
                                     + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
                                     + " curCachedImpAdj=" + curCachedImpAdj + ")");
-                            break;
-                        default:
-                            // Figure out the next cached level.
-                            if (curEmptyAdj != nextEmptyAdj) {
-                                stepEmpty++;
-                                if (stepEmpty >= emptyFactor) {
-                                    stepEmpty = 0;
-                                    curEmptyAdj = nextEmptyAdj;
-                                    nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
-                                    if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
-                                        nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
-                                    }
+                        }
+                        break;
+                    default:
+                        // Figure out the next cached level.
+                        if (curEmptyAdj != nextEmptyAdj) {
+                            stepEmpty++;
+                            if (stepEmpty >= emptyFactor) {
+                                stepEmpty = 0;
+                                curEmptyAdj = nextEmptyAdj;
+                                nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+                                if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
+                                    nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                 }
                             }
-                            // For everything else, assign next empty cached process
-                            // level and bump that up.  Note that this means that
-                            // long-running services that have dropped down to the
-                            // cached level will be treated as empty (since their process
-                            // state is still as a service), which is what we want.
-                            app.setCurRawAdj(curEmptyAdj);
-                            app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
-                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
+                        }
+                        // For everything else, assign next empty cached process
+                        // level and bump that up.  Note that this means that
+                        // long-running services that have dropped down to the
+                        // cached level will be treated as empty (since their process
+                        // state is still as a service), which is what we want.
+                        app.setCurRawAdj(curEmptyAdj);
+                        app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
+                        if (DEBUG_LRU) {
+                            Slog.d(TAG_LRU, "Assigning empty LRU #" + i
                                     + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
                                     + ")");
-                            break;
-                    }
+                        }
+                        break;
                 }
             }
         }
+    }
 
-        // Cycle strategy:
-        // - Retry computing any process that has encountered a cycle.
-        // - Continue retrying until no process was promoted.
-        // - Iterate from least important to most important.
-        int cycleCount = 0;
-        while (retryCycles && cycleCount < 10) {
-            cycleCount++;
-            retryCycles = false;
+    private boolean updateAndTrimProcessLocked(final long now, final long nowElapsed,
+            final long oldTime, final ActiveUids activeUids) {
+        ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
+        final int numLru = lruList.size();
 
-            for (int i = 0; i < N; i++) {
-                ProcessRecord app = mProcessList.mLruProcesses.get(i);
-                if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
-                    app.adjSeq--;
-                    app.completedAdjSeq--;
-                }
-            }
+        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
+        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES
+                - emptyProcessLimit;
+        int lastCachedGroup = 0;
+        int lastCachedGroupUid = 0;
+        int numCached = 0;
+        int numCachedExtraGroup = 0;
+        int numEmpty = 0;
+        int numTrimming = 0;
 
-            for (int i = 0; i < N; i++) {
-                ProcessRecord app = mProcessList.mLruProcesses.get(i);
-                if (!app.killedByAm && app.thread != null && app.containsCycle == true) {
-                    if (computeOomAdjLocked(app, app.getCurRawAdj(), TOP_APP, true, now,
-                            true)) {
-                        retryCycles = true;
-                    }
-                }
-            }
-        }
-
-        lastCachedGroup = lastCachedGroupUid = 0;
-
-        for (int i = N - 1; i >= 0; i--) {
-            ProcessRecord app = mProcessList.mLruProcesses.get(i);
+        for (int i = numLru - 1; i >= 0; i--) {
+            ProcessRecord app = lruList.get(i);
             if (!app.killedByAm && app.thread != null) {
-                applyOomAdjLocked(app, true, now, nowElapsed);
+                // We don't need to apply the update for the process which didn't get computed
+                if (app.completedAdjSeq == mAdjSeq) {
+                    applyOomAdjLocked(app, true, now, nowElapsed);
+                }
 
                 // Count the number of process types.
                 switch (app.getCurProcState()) {
@@ -512,16 +763,7 @@
                     app.kill("isolated not needed", true);
                 } else {
                     // Keeping this process, update its uid.
-                    final UidRecord uidRec = app.uidRecord;
-                    if (uidRec != null) {
-                        uidRec.ephemeral = app.info.isInstantApp();
-                        if (uidRec.getCurProcState() > app.getCurProcState()) {
-                            uidRec.setCurProcState(app.getCurProcState());
-                        }
-                        if (app.hasForegroundServices()) {
-                            uidRec.foregroundServices = true;
-                        }
-                    }
+                    updateAppUidRecLocked(app);
                 }
 
                 if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
@@ -531,31 +773,34 @@
             }
         }
 
-        mService.incrementProcStateSeqAndNotifyAppsLocked();
+        mProcessList.incrementProcStateSeqAndNotifyAppsLocked(activeUids);
 
-        mNumServiceProcs = mNewNumServiceProcs;
+        return mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
+    }
 
-        boolean allChanged = mService.updateLowMemStateLocked(numCached, numEmpty, numTrimming);
-
-        if (mService.mAlwaysFinishActivities) {
-            // Need to do this on its own message because the stack may not
-            // be in a consistent state at this point.
-            mService.mAtmInternal.scheduleDestroyAllActivities("always-finish");
+    private void updateAppUidRecLocked(ProcessRecord app) {
+        final UidRecord uidRec = app.uidRecord;
+        if (uidRec != null) {
+            uidRec.ephemeral = app.info.isInstantApp();
+            if (uidRec.getCurProcState() > app.getCurProcState()) {
+                uidRec.setCurProcState(app.getCurProcState());
+            }
+            if (app.hasForegroundServices()) {
+                uidRec.foregroundServices = true;
+            }
         }
+    }
 
-        if (allChanged) {
-            mService.requestPssAllProcsLocked(now, false,
-                    mService.mProcessStats.isMemFactorLowered());
-        }
-
-        ArrayList<UidRecord> becameIdle = null;
+    private void updateUidsLocked(ActiveUids activeUids, final long nowElapsed) {
+        ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
+        becameIdle.clear();
 
         // Update from any uid changes.
         if (mLocalPowerManager != null) {
             mLocalPowerManager.startUidChanges();
         }
-        for (int i = mActiveUids.size() - 1; i >= 0; i--) {
-            final UidRecord uidRec = mActiveUids.valueAt(i);
+        for (int i = activeUids.size() - 1; i >= 0; i--) {
+            final UidRecord uidRec = activeUids.valueAt(i);
             int uidChange = UidRecord.CHANGE_PROCSTATE;
             if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
                     && (uidRec.setProcState != uidRec.getCurProcState()
@@ -582,9 +827,6 @@
                     }
                     if (uidRec.idle && !uidRec.setIdle) {
                         uidChange = UidRecord.CHANGE_IDLE;
-                        if (becameIdle == null) {
-                            becameIdle = new ArrayList<>();
-                        }
                         becameIdle.add(uidRec);
                     }
                 } else {
@@ -617,40 +859,21 @@
             mLocalPowerManager.finishUidChanges();
         }
 
-        if (becameIdle != null) {
+        int size = becameIdle.size();
+        if (size > 0) {
             // If we have any new uids that became idle this time, we need to make sure
             // they aren't left with running services.
-            for (int i = becameIdle.size() - 1; i >= 0; i--) {
+            for (int i = size - 1; i >= 0; i--) {
                 mService.mServices.stopInBackgroundLocked(becameIdle.get(i).uid);
             }
         }
-
-        if (mService.mProcessStats.shouldWriteNowLocked(now)) {
-            mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
-                    mService.mProcessStats));
-        }
-
-        // Run this after making sure all procstates are updated.
-        mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
-
-        if (DEBUG_OOM_ADJ) {
-            final long duration = SystemClock.uptimeMillis() - now;
-            if (false) {
-                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",
-                        new RuntimeException("here").fillInStackTrace());
-            } else {
-                Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");
-            }
-        }
-        mService.mOomAdjProfiler.oomAdjEnded();
-        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
     private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
             new ComputeOomAdjWindowCallback();
 
     /** These methods are called inline during computeOomAdjLocked(), on the same thread */
-    private final class ComputeOomAdjWindowCallback
+    final class ComputeOomAdjWindowCallback
             implements WindowProcessController.ComputeOomAdjCallback {
 
         ProcessRecord app;
@@ -771,7 +994,8 @@
     }
 
     private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
-            ProcessRecord TOP_APP, boolean doingAll, long now, boolean cycleReEval) {
+            ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
+            boolean computeClients) {
         if (mAdjSeq == app.adjSeq) {
             if (app.adjSeq == app.completedAdjSeq) {
                 // This adjustment has already been computed successfully.
@@ -801,7 +1025,6 @@
         app.empty = false;
         app.cached = false;
 
-        final WindowProcessController wpc = app.getWindowProcessController();
         final int appUid = app.info.uid;
         final int logUid = mService.mCurOomAdjUid;
 
@@ -825,7 +1048,7 @@
             // facilitate this, here we need to determine whether or not it
             // is currently showing UI.
             app.systemNoUi = true;
-            if (app == TOP_APP) {
+            if (app == topApp) {
                 app.systemNoUi = false;
                 app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_TOP_APP);
                 app.adjType = "pers-top-activity";
@@ -833,7 +1056,7 @@
                 // sched group/proc state adjustment is below
                 app.systemNoUi = false;
                 app.adjType = "pers-top-ui";
-            } else if (wpc.hasVisibleActivities()) {
+            } else if (app.getCachedHasVisibleActivities()) {
                 app.systemNoUi = false;
             }
             if (!app.systemNoUi) {
@@ -866,8 +1089,7 @@
         int cachedAdjSeq;
 
         boolean foregroundActivities = false;
-        mTmpBroadcastQueue.clear();
-        if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == TOP_APP) {
+        if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
             // The last app on the list is the foreground app.
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
@@ -894,7 +1116,7 @@
             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making instrumentation: " + app);
             }
-        } else if (mService.isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
+        } else if (app.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) {
             // An app that is currently receiving a broadcast also
             // counts as being in the foreground for OOM killer purposes.
             // It's placed in a sched group based on the nature of the
@@ -919,7 +1141,7 @@
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Making exec-service: " + app);
             }
             //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
-        } else if (app == TOP_APP) {
+        } else if (app == topApp) {
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
             app.adjType = "top-sleeping";
@@ -944,24 +1166,19 @@
         }
 
         // Examine all activities if not already foreground.
-        if (!foregroundActivities && wpc.hasActivities()) {
-            mTmpComputeOomAdjWindowCallback.initialize(app, adj, foregroundActivities, procState,
-                    schedGroup, appUid, logUid, PROCESS_STATE_CUR_TOP);
-            final int minLayer = wpc.computeOomAdjFromActivities(
-                    ProcessList.VISIBLE_APP_LAYER_MAX, mTmpComputeOomAdjWindowCallback);
+        if (!foregroundActivities && app.getCachedHasActivities()) {
+            app.computeOomAdjFromActivitiesIfNecessary(mTmpComputeOomAdjWindowCallback,
+                    adj, foregroundActivities, procState, schedGroup, appUid, logUid,
+                    PROCESS_STATE_CUR_TOP);
 
-            adj = mTmpComputeOomAdjWindowCallback.adj;
-            foregroundActivities = mTmpComputeOomAdjWindowCallback.foregroundActivities;
-            procState = mTmpComputeOomAdjWindowCallback.procState;
-            schedGroup = mTmpComputeOomAdjWindowCallback.schedGroup;
-
-            if (adj == ProcessList.VISIBLE_APP_ADJ) {
-                adj += minLayer;
-            }
+            adj = app.mCachedAdj;
+            foregroundActivities = app.mCachedForegroundActivities;
+            procState = app.mCachedProcState;
+            schedGroup = app.mCachedSchedGroup;
         }
 
-        if (procState > ActivityManager.PROCESS_STATE_CACHED_RECENT && app.hasRecentTasks()) {
-            procState = ActivityManager.PROCESS_STATE_CACHED_RECENT;
+        if (procState > PROCESS_STATE_CACHED_RECENT && app.getCachedHasRecentTasks()) {
+            procState = PROCESS_STATE_CACHED_RECENT;
             app.adjType = "cch-rec";
             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise procstate to cached recent: " + app);
@@ -1031,7 +1248,7 @@
             }
         }
 
-        if (mService.mAtmInternal.isHeavyWeightProcess(app.getWindowProcessController())) {
+        if (app.getCachedIsHeavyWeight()) {
             if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                 // We don't want to kill the current heavy-weight process.
                 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
@@ -1051,7 +1268,7 @@
             }
         }
 
-        if (wpc.isHomeProcess()) {
+        if (app.getCachedIsHomeProcess()) {
             if (adj > ProcessList.HOME_APP_ADJ) {
                 // This process is hosting what we currently consider to be the
                 // home app, so we don't want to let it go into the background.
@@ -1072,7 +1289,7 @@
             }
         }
 
-        if (wpc.isPreviousProcess() && app.hasActivities()) {
+        if (app.getCachedIsPreviousProcess() && app.getCachedHasActivities()) {
             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                 // This was the previous process that showed UI to the user.
                 // We want to try to keep it around more aggressively, to give
@@ -1153,7 +1370,7 @@
                                 "Raise procstate to started service: " + app);
                     }
                 }
-                if (app.hasShownUi && !wpc.isHomeProcess()) {
+                if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
                     // If this process has shown some UI, let it immediately
                     // go to the LRU list because it may be pretty heavy with
                     // UI stuff.  We'll tag it with a label just to help
@@ -1208,7 +1425,13 @@
                     boolean trackedProcState = false;
                     if ((cr.flags& Context.BIND_WAIVE_PRIORITY) == 0) {
                         ProcessRecord client = cr.binding.client;
-                        computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval);
+                        if (computeClients) {
+                            computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now,
+                                    cycleReEval, true);
+                        } else {
+                            client.setCurRawAdj(client.setAdj);
+                            client.setCurRawProcState(client.setProcState);
+                        }
 
                         if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
                             continue;
@@ -1227,7 +1450,7 @@
                         if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                             // Not doing bind OOM management, so treat
                             // this guy more like a started service.
-                            if (app.hasShownUi && !wpc.isHomeProcess()) {
+                            if (app.hasShownUi && !app.getCachedIsHomeProcess()) {
                                 // If this process has shown some UI, let it immediately
                                 // go to the LRU list because it may be pretty heavy with
                                 // UI stuff.  We'll tag it with a label just to help
@@ -1261,7 +1484,7 @@
                             // about letting this process get into the LRU
                             // list to be killed and restarted if needed for
                             // memory.
-                            if (app.hasShownUi && !wpc.isHomeProcess()
+                            if (app.hasShownUi && !app.getCachedIsHomeProcess()
                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
                                     adjType = "cch-bound-ui-services";
@@ -1451,7 +1674,13 @@
                     // Being our own client is not interesting.
                     continue;
                 }
-                computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now, cycleReEval);
+                if (computeClients) {
+                    computeOomAdjLocked(client, cachedAdj, topApp, doingAll, now, cycleReEval,
+                            true);
+                } else {
+                    client.setCurRawAdj(client.setAdj);
+                    client.setCurRawProcState(client.setProcState);
+                }
 
                 if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) {
                     continue;
@@ -1467,7 +1696,7 @@
                 }
                 String adjType = null;
                 if (adj > clientAdj) {
-                    if (app.hasShownUi && !wpc.isHomeProcess()
+                    if (app.hasShownUi && !app.getCachedIsHomeProcess()
                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                         adjType = "cch-ui-provider";
                     } else {
@@ -1565,7 +1794,7 @@
         if (procState >= PROCESS_STATE_CACHED_EMPTY) {
             if (app.hasClientActivities()) {
                 // This is a cached process, but with client activities.  Mark it so.
-                procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
+                procState = PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
                 app.adjType = "cch-client-act";
             } else if (app.treatLikeActivity) {
                 // This is a cached process, but somebody wants us to treat it like it has
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index af126f2..8163a6d 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -20,6 +20,8 @@
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 import static android.os.Process.getFreeMemory;
@@ -28,6 +30,7 @@
 import static android.os.Process.startWebView;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
@@ -41,6 +44,7 @@
 import static com.android.server.am.ActivityManagerService.PROC_START_TIMEOUT_WITH_WRAPPER;
 import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
 import static com.android.server.am.ActivityManagerService.TAG_LRU;
+import static com.android.server.am.ActivityManagerService.TAG_NETWORK;
 import static com.android.server.am.ActivityManagerService.TAG_PROCESSES;
 import static com.android.server.am.ActivityManagerService.TAG_PSS;
 import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS;
@@ -240,6 +244,24 @@
     // Threshold of number of cached+empty where we consider memory critical.
     static final int TRIM_LOW_THRESHOLD = 5;
 
+    /**
+     * State indicating that there is no need for any blocking for network.
+     */
+    @VisibleForTesting
+    static final int NETWORK_STATE_NO_CHANGE = 0;
+
+    /**
+     * State indicating that the main thread needs to be informed about the network wait.
+     */
+    @VisibleForTesting
+    static final int NETWORK_STATE_BLOCK = 1;
+
+    /**
+     * State indicating that any threads waiting for network state to get updated can be unblocked.
+     */
+    @VisibleForTesting
+    static final int NETWORK_STATE_UNBLOCK = 2;
+
     // If true, then we pass the flag to ART to load the app image startup cache.
     private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE =
             "persist.device_config.runtime_native.use_app_image_startup_cache";
@@ -3189,4 +3211,113 @@
             mService.doStopUidLocked(uidRec.uid, uidRec);
         }
     }
+
+    /**
+     * Checks if the uid is coming from background to foreground or vice versa and returns
+     * appropriate block state based on this.
+     *
+     * @return blockState based on whether the uid is coming from background to foreground or
+     *         vice versa. If bg->fg or fg->bg, then {@link #NETWORK_STATE_BLOCK} or
+     *         {@link #NETWORK_STATE_UNBLOCK} respectively, otherwise
+     *         {@link #NETWORK_STATE_NO_CHANGE}.
+     */
+    @VisibleForTesting
+    int getBlockStateForUid(UidRecord uidRec) {
+        // Denotes whether uid's process state is currently allowed network access.
+        final boolean isAllowed =
+                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
+                || isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
+        // Denotes whether uid's process state was previously allowed network access.
+        final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
+                || isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
+
+        // When the uid is coming to foreground, AMS should inform the app thread that it should
+        // block for the network rules to get updated before launching an activity.
+        if (!wasAllowed && isAllowed) {
+            return NETWORK_STATE_BLOCK;
+        }
+        // When the uid is going to background, AMS should inform the app thread that if an
+        // activity launch is blocked for the network rules to get updated, it should be unblocked.
+        if (wasAllowed && !isAllowed) {
+            return NETWORK_STATE_UNBLOCK;
+        }
+        return NETWORK_STATE_NO_CHANGE;
+    }
+
+    /**
+     * Checks if any uid is coming from background to foreground or vice versa and if so, increments
+     * the {@link UidRecord#curProcStateSeq} corresponding to that uid using global seq counter
+     * {@link ProcessList#mProcStateSeqCounter} and notifies the app if it needs to block.
+     */
+    @VisibleForTesting
+    @GuardedBy("mService")
+    void incrementProcStateSeqAndNotifyAppsLocked(ActiveUids activeUids) {
+        if (mService.mWaitForNetworkTimeoutMs <= 0) {
+            return;
+        }
+        // Used for identifying which uids need to block for network.
+        ArrayList<Integer> blockingUids = null;
+        for (int i = activeUids.size() - 1; i >= 0; --i) {
+            final UidRecord uidRec = activeUids.valueAt(i);
+            // If the network is not restricted for uid, then nothing to do here.
+            if (!mService.mInjector.isNetworkRestrictedForUid(uidRec.uid)) {
+                continue;
+            }
+            if (!UserHandle.isApp(uidRec.uid) || !uidRec.hasInternetPermission) {
+                continue;
+            }
+            // If process state is not changed, then there's nothing to do.
+            if (uidRec.setProcState == uidRec.getCurProcState()) {
+                continue;
+            }
+            final int blockState = getBlockStateForUid(uidRec);
+            // No need to inform the app when the blockState is NETWORK_STATE_NO_CHANGE as
+            // there's nothing the app needs to do in this scenario.
+            if (blockState == NETWORK_STATE_NO_CHANGE) {
+                continue;
+            }
+            synchronized (uidRec.networkStateLock) {
+                uidRec.curProcStateSeq = ++mProcStateSeqCounter; // TODO: use method
+                if (blockState == NETWORK_STATE_BLOCK) {
+                    if (blockingUids == null) {
+                        blockingUids = new ArrayList<>();
+                    }
+                    blockingUids.add(uidRec.uid);
+                } else {
+                    if (DEBUG_NETWORK) {
+                        Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
+                                + " threads for uid: " + uidRec);
+                    }
+                    if (uidRec.waitingForNetwork) {
+                        uidRec.networkStateLock.notifyAll();
+                    }
+                }
+            }
+        }
+
+        // There are no uids that need to block, so nothing more to do.
+        if (blockingUids == null) {
+            return;
+        }
+
+        for (int i = mLruProcesses.size() - 1; i >= 0; --i) {
+            final ProcessRecord app = mLruProcesses.get(i);
+            if (!blockingUids.contains(app.uid)) {
+                continue;
+            }
+            if (!app.killedByAm && app.thread != null) {
+                final UidRecord uidRec = getUidRecordLocked(app.uid);
+                try {
+                    if (DEBUG_NETWORK) {
+                        Slog.d(TAG_NETWORK, "Informing app thread that it needs to block: "
+                                + uidRec);
+                    }
+                    if (uidRec != null) {
+                        app.thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
+                    }
+                } catch (RemoteException ignored) {
+                }
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index ea30842..bf43f3b 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -308,6 +308,22 @@
     // This will be same as {@link #uid} usually except for some apps used during factory testing.
     int startUid;
 
+    // Cached task info for OomAdjuster
+    private static final int VALUE_INVALID = -1;
+    private static final int VALUE_FALSE = 0;
+    private static final int VALUE_TRUE = 1;
+    private int mCachedHasActivities = VALUE_INVALID;
+    private int mCachedIsHeavyWeight = VALUE_INVALID;
+    private int mCachedHasVisibleActivities = VALUE_INVALID;
+    private int mCachedIsHomeProcess = VALUE_INVALID;
+    private int mCachedIsPreviousProcess = VALUE_INVALID;
+    private int mCachedHasRecentTasks = VALUE_INVALID;
+    private int mCachedIsReceivingBroadcast = VALUE_INVALID;
+    int mCachedAdj = ProcessList.INVALID_ADJ;
+    boolean mCachedForegroundActivities = false;
+    int mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+    int mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
             long startTime) {
         this.startUid = startUid;
@@ -1302,7 +1318,7 @@
             }
             mService.mProcessList.updateLruProcessLocked(this, activityChange, null /* client */);
             if (updateOomAdj) {
-                mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_ACTIVITY);
+                mService.updateOomAdjLocked(this, OomAdjuster.OOM_ADJ_REASON_ACTIVITY);
             }
         }
     }
@@ -1650,4 +1666,100 @@
         return Settings.Secure.getInt(mService.mContext.getContentResolver(),
                 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
     }
+
+    void resetCachedInfo() {
+        mCachedHasActivities = VALUE_INVALID;
+        mCachedIsHeavyWeight = VALUE_INVALID;
+        mCachedHasVisibleActivities = VALUE_INVALID;
+        mCachedIsHomeProcess = VALUE_INVALID;
+        mCachedIsPreviousProcess = VALUE_INVALID;
+        mCachedHasRecentTasks = VALUE_INVALID;
+        mCachedIsReceivingBroadcast = VALUE_INVALID;
+        mCachedAdj = ProcessList.INVALID_ADJ;
+        mCachedForegroundActivities = false;
+        mCachedProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+        mCachedSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
+    }
+
+    boolean getCachedHasActivities() {
+        if (mCachedHasActivities == VALUE_INVALID) {
+            mCachedHasActivities = getWindowProcessController().hasActivities() ? VALUE_TRUE
+                    : VALUE_FALSE;
+        }
+        return mCachedHasActivities == VALUE_TRUE;
+    }
+
+    boolean getCachedIsHeavyWeight() {
+        if (mCachedIsHeavyWeight == VALUE_INVALID) {
+            mCachedIsHeavyWeight = mService.mAtmInternal.isHeavyWeightProcess(
+                    getWindowProcessController()) ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedIsHeavyWeight == VALUE_TRUE;
+    }
+
+    boolean getCachedHasVisibleActivities() {
+        if (mCachedHasVisibleActivities == VALUE_INVALID) {
+            mCachedHasVisibleActivities = getWindowProcessController().hasVisibleActivities()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedHasVisibleActivities == VALUE_TRUE;
+    }
+
+    boolean getCachedIsHomeProcess() {
+        if (mCachedIsHomeProcess == VALUE_INVALID) {
+            mCachedIsHomeProcess = getWindowProcessController().isHomeProcess()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedIsHomeProcess == VALUE_TRUE;
+    }
+
+    boolean getCachedIsPreviousProcess() {
+        if (mCachedIsPreviousProcess == VALUE_INVALID) {
+            mCachedIsPreviousProcess = getWindowProcessController().isPreviousProcess()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedIsPreviousProcess == VALUE_TRUE;
+    }
+
+    boolean getCachedHasRecentTasks() {
+        if (mCachedHasRecentTasks == VALUE_INVALID) {
+            mCachedHasRecentTasks = getWindowProcessController().hasRecentTasks()
+                    ? VALUE_TRUE : VALUE_FALSE;
+        }
+        return mCachedHasRecentTasks == VALUE_TRUE;
+    }
+
+    boolean getCachedIsReceivingBroadcast(ArraySet<BroadcastQueue> tmpQueue) {
+        if (mCachedIsReceivingBroadcast == VALUE_INVALID) {
+            tmpQueue.clear();
+            mCachedIsReceivingBroadcast = mService.isReceivingBroadcastLocked(this, tmpQueue)
+                    ? VALUE_TRUE : VALUE_FALSE;
+            if (mCachedIsReceivingBroadcast == VALUE_TRUE) {
+                mCachedSchedGroup = tmpQueue.contains(mService.mFgBroadcastQueue)
+                        ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
+            }
+        }
+        return mCachedIsReceivingBroadcast == VALUE_TRUE;
+    }
+
+    void computeOomAdjFromActivitiesIfNecessary(OomAdjuster.ComputeOomAdjWindowCallback callback,
+            int adj, boolean foregroundActivities, int procState, int schedGroup, int appUid,
+            int logUid, int processCurTop) {
+        if (mCachedAdj != ProcessList.INVALID_ADJ) {
+            return;
+        }
+        callback.initialize(this, adj, foregroundActivities, procState, schedGroup, appUid, logUid,
+                processCurTop);
+        final int minLayer = getWindowProcessController().computeOomAdjFromActivities(
+                ProcessList.VISIBLE_APP_LAYER_MAX, callback);
+
+        mCachedAdj = callback.adj;
+        mCachedForegroundActivities = callback.foregroundActivities;
+        mCachedProcState = callback.procState;
+        mCachedSchedGroup = callback.schedGroup;
+
+        if (mCachedAdj == ProcessList.VISIBLE_APP_ADJ) {
+            mCachedAdj += minLayer;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 2ac6eb0..8575068 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -47,6 +47,7 @@
 import android.app.AppOpsManager.HistoricalOps;
 import android.app.AppOpsManager.HistoricalOpsRequest;
 import android.app.AppOpsManager.Mode;
+import android.app.AppOpsManager.OpFeatureEntry;
 import android.app.AppOpsManager.OpEntry;
 import android.app.AppOpsManager.OpFlags;
 import android.app.AppOpsManagerInternal;
@@ -141,6 +142,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 public class AppOpsService extends IAppOpsService.Stub {
     static final String TAG = "AppOps";
@@ -363,7 +365,9 @@
         public int pendingState = UID_STATE_CACHED;
         public long pendingStateCommitTime;
 
+        // For all features combined
         public int startNesting;
+
         public ArrayMap<String, Ops> pkgOps;
         public SparseIntArray opModes;
 
@@ -453,21 +457,133 @@
         }
     }
 
-    final static class Op {
-        int op;
-        boolean running;
-        final UidState uidState;
-        final @NonNull String packageName;
+    private static final class FeatureOp {
+        public final @NonNull Op parent;
 
-        private @Mode int mode;
+        public boolean running;
+
         private @Nullable LongSparseLongArray mAccessTimes;
         private @Nullable LongSparseLongArray mRejectTimes;
         private @Nullable LongSparseLongArray mDurations;
         private @Nullable LongSparseLongArray mProxyUids;
+        private @Nullable LongSparseArray<String> mProxyFeatureIds;
         private @Nullable LongSparseArray<String> mProxyPackageNames;
 
-        int startNesting;
-        long startRealtime;
+        public int startNesting;
+        public long startRealtime;
+
+        FeatureOp(@NonNull Op parent) {
+            this.parent = parent;
+        }
+
+        public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
+                @Nullable String proxyFeatureId, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mAccessTimes == null) {
+                mAccessTimes = new LongSparseLongArray();
+            }
+            mAccessTimes.put(key, time);
+            updateProxyState(key, proxyUid, proxyPackageName, proxyFeatureId);
+            if (mDurations != null) {
+                mDurations.delete(key);
+            }
+        }
+
+        public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
+                @Nullable String proxyFeatureId, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mRejectTimes == null) {
+                mRejectTimes = new LongSparseLongArray();
+            }
+            mRejectTimes.put(key, time);
+            updateProxyState(key, proxyUid, proxyPackageName, proxyFeatureId);
+            if (mDurations != null) {
+                mDurations.delete(key);
+            }
+        }
+
+        public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
+            running = true;
+        }
+
+        public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, duration, uidState, flags);
+            running = false;
+        }
+
+        public void running(long time, long duration, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, duration, uidState, flags);
+        }
+
+        public void continuing(long duration, @AppOpsManager.UidState int uidState,
+                @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mDurations == null) {
+                mDurations = new LongSparseLongArray();
+            }
+            mDurations.put(key, duration);
+        }
+
+        private void updateAccessTimeAndDuration(long time, long duration,
+                @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mAccessTimes == null) {
+                mAccessTimes = new LongSparseLongArray();
+            }
+            mAccessTimes.put(key, time);
+            if (mDurations == null) {
+                mDurations = new LongSparseLongArray();
+            }
+            mDurations.put(key, duration);
+        }
+
+        private void updateProxyState(long key, int proxyUid,
+                @Nullable String proxyPackageName, @Nullable String featureId) {
+            if (proxyUid == Process.INVALID_UID) {
+                return;
+            }
+
+            if (mProxyUids == null) {
+                mProxyUids = new LongSparseLongArray();
+            }
+            mProxyUids.put(key, proxyUid);
+
+            if (mProxyPackageNames == null) {
+                mProxyPackageNames = new LongSparseArray<>();
+            }
+            mProxyPackageNames.put(key, proxyPackageName);
+
+            if (mProxyFeatureIds == null) {
+                mProxyFeatureIds = new LongSparseArray<>();
+            }
+            mProxyFeatureIds.put(key, featureId);
+        }
+
+        boolean hasAnyTime() {
+            return (mAccessTimes != null && mAccessTimes.size() > 0)
+                    || (mRejectTimes != null && mRejectTimes.size() > 0);
+        }
+
+        @NonNull OpFeatureEntry.Builder createFeatureEntryBuilderLocked() {
+            return new OpFeatureEntry.Builder(running, mAccessTimes, mRejectTimes, mDurations,
+                    mProxyUids, mProxyPackageNames, mProxyFeatureIds);
+        }
+    }
+
+    final static class Op {
+        int op;
+        final UidState uidState;
+        final @NonNull String packageName;
+
+        private @Mode int mode;
+
+        /** featureId -> FeatureOp */
+        final ArrayMap<String, FeatureOp> mFeatures = new ArrayMap<>(1);
 
         Op(UidState uidState, String packageName, int op) {
             this.op = op;
@@ -484,95 +600,54 @@
             return uidState.evalMode(op, mode);
         }
 
-        /** @hide */
-        public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
-            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mAccessTimes == null) {
-                mAccessTimes = new LongSparseLongArray();
-            }
-            mAccessTimes.put(key, time);
-            updateProxyState(key, proxyUid, proxyPackageName);
-            if (mDurations != null) {
-                mDurations.delete(key);
+        void removeFeaturesWithNoTime() {
+            for (int i = mFeatures.size() - 1; i >= 0; i--) {
+                if (!mFeatures.valueAt(i).hasAnyTime()) {
+                    mFeatures.removeAt(i);
+                }
             }
         }
 
-        /** @hide */
-        public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
-            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mRejectTimes == null) {
-                mRejectTimes = new LongSparseLongArray();
+        private @NonNull FeatureOp getOrCreateFeature(@NonNull Op parent,
+                @Nullable String featureId) {
+            FeatureOp featureOp;
+
+            featureOp = mFeatures.get(featureId);
+            if (featureOp == null) {
+                featureOp = new FeatureOp(parent);
+                mFeatures.put(featureId, featureOp);
             }
-            mRejectTimes.put(key, time);
-            updateProxyState(key, proxyUid, proxyPackageName);
-            if (mDurations != null) {
-                mDurations.delete(key);
-            }
+
+            return featureOp;
         }
 
-        /** @hide */
-        public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
-            running = true;
-        }
+        @NonNull OpEntry createEntryLocked() {
+            final int numFeatures = mFeatures.size();
 
-        /** @hide */
-        public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
-            @OpFlags int flags) {
-            updateAccessTimeAndDuration(time, duration, uidState, flags);
-            running = false;
-        }
-
-        /** @hide */
-        public void running(long time, long duration, @AppOpsManager.UidState int uidState,
-            @OpFlags int flags) {
-            updateAccessTimeAndDuration(time, duration, uidState, flags);
-        }
-
-        /** @hide */
-        public void continuing(long duration, @AppOpsManager.UidState int uidState,
-            @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mDurations == null) {
-                mDurations = new LongSparseLongArray();
-            }
-            mDurations.put(key, duration);
-        }
-
-        private void updateAccessTimeAndDuration(long time, long duration,
-            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
-            final long key = AppOpsManager.makeKey(uidState, flags);
-            if (mAccessTimes == null) {
-                mAccessTimes = new LongSparseLongArray();
-            }
-            mAccessTimes.put(key, time);
-            if (mDurations == null) {
-                mDurations = new LongSparseLongArray();
-            }
-            mDurations.put(key, duration);
-        }
-
-        private void updateProxyState(long key, int proxyUid,
-            @Nullable String proxyPackageName) {
-            if (proxyUid == Process.INVALID_UID) {
-                return;
+            final Pair<String, OpFeatureEntry.Builder>[] featureEntries =
+                    new Pair[numFeatures];
+            for (int i = 0; i < numFeatures; i++) {
+                featureEntries[i] = new Pair<>(mFeatures.keyAt(i),
+                        mFeatures.valueAt(i).createFeatureEntryBuilderLocked());
             }
 
-            if (mProxyUids == null) {
-                mProxyUids = new LongSparseLongArray();
-            }
-            mProxyUids.put(key, proxyUid);
-            if (mProxyPackageNames == null) {
-                mProxyPackageNames = new LongSparseArray<>();
-            }
-            mProxyPackageNames.put(key, proxyPackageName);
+            return new OpEntry(op, mode, featureEntries);
         }
 
-        boolean hasAnyTime() {
-            return (mAccessTimes != null && mAccessTimes.size() > 0)
-                || (mRejectTimes != null && mRejectTimes.size() > 0);
+        @NonNull OpEntry createSingleFeatureEntryLocked(@Nullable String featureId) {
+            final int numFeatures = mFeatures.size();
+
+            final Pair<String, AppOpsManager.OpFeatureEntry.Builder>[] featureEntries =
+                    new Pair[1];
+            for (int i = 0; i < numFeatures; i++) {
+                if (Objects.equals(mFeatures.keyAt(i), featureId)) {
+                    featureEntries[0] = new Pair<>(mFeatures.keyAt(i),
+                            mFeatures.valueAt(i).createFeatureEntryBuilderLocked());
+                    break;
+                }
+            }
+
+            return new OpEntry(op, mode, featureEntries);
         }
     }
 
@@ -726,7 +801,7 @@
     final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
 
     final class ClientState extends Binder implements DeathRecipient {
-        final ArrayList<Op> mStartedOps = new ArrayList<>();
+        final ArrayList<Pair<Op, String>> mStartedOps = new ArrayList<>();
         final IBinder mAppToken;
         final int mPid;
 
@@ -755,9 +830,12 @@
         public void binderDied() {
             synchronized (AppOpsService.this) {
                 for (int i=mStartedOps.size()-1; i>=0; i--) {
-                    final Op op = mStartedOps.get(i);
-                    finishOperationLocked(op, /*finishNested*/ true);
-                    if (op.startNesting <= 0) {
+                    final Pair<Op, String> startedOp = mStartedOps.get(i);
+                    final Op op = startedOp.first;
+                    final String featureId = startedOp.second;
+
+                    finishOperationLocked(op, featureId, /*finishNested*/ true);
+                    if (op.mFeatures.get(featureId).startNesting <= 0) {
                         scheduleOpActiveChangedIfNeededLocked(op.op, op.uidState.uid,
                                 op.packageName, false);
                     }
@@ -889,11 +967,11 @@
                                 return Zygote.MOUNT_EXTERNAL_NONE;
                             }
                             if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
-                                    packageName) != AppOpsManager.MODE_ALLOWED) {
+                                    packageName, null) != AppOpsManager.MODE_ALLOWED) {
                                 return Zygote.MOUNT_EXTERNAL_NONE;
                             }
                             if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
-                                    packageName) != AppOpsManager.MODE_ALLOWED) {
+                                    packageName, null) != AppOpsManager.MODE_ALLOWED) {
                                 return Zygote.MOUNT_EXTERNAL_READ;
                             }
                             return Zygote.MOUNT_EXTERNAL_WRITE;
@@ -936,13 +1014,16 @@
                 if (client.mStartedOps == null) {
                     continue;
                 }
-                final int opCount = client.mStartedOps.size();
-                for (int j = opCount - 1; j >= 0; j--) {
-                    final Op op = client.mStartedOps.get(j);
+                final int startedOpCount = client.mStartedOps.size();
+                for (int j = startedOpCount - 1; j >= 0; j--) {
+                    final Pair<Op, String> startedOp = client.mStartedOps.get(j);
+                    final Op op = startedOp.first;
+                    final String featureId = startedOp.second;
+
                     if (uid == op.uidState.uid && packageName.equals(op.packageName)) {
-                        finishOperationLocked(op, /*finishNested*/ true);
+                        finishOperationLocked(op, featureId, /*finishNested*/ true);
                         client.mStartedOps.remove(j);
-                        if (op.startNesting <= 0) {
+                        if (op.mFeatures.get(featureId).startNesting <= 0) {
                             scheduleOpActiveChangedIfNeededLocked(op.op,
                                     uid, packageName, false);
                         }
@@ -954,11 +1035,16 @@
                 scheduleFastWriteLocked();
 
                 final int opCount = ops.size();
-                for (int i = 0; i < opCount; i++) {
-                    final Op op = ops.valueAt(i);
-                    if (op.running) {
-                        scheduleOpActiveChangedIfNeededLocked(
-                                op.op, op.uidState.uid, op.packageName, false);
+                for (int opNum = 0; opNum < opCount; opNum++) {
+                    final Op op = ops.valueAt(opNum);
+
+                    final int numFeatures = op.mFeatures.size();
+                    for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+                        if (op.mFeatures.valueAt(featureNum).running) {
+                            scheduleOpActiveChangedIfNeededLocked(
+                                    op.op, op.uidState.uid, op.packageName, false);
+                            break;
+                        }
                     }
                 }
             }
@@ -1011,19 +1097,26 @@
                         final Ops ops = uidState.pkgOps.valueAt(i);
                         for (int j = ops.size() - 1; j >= 0; j--) {
                             final Op op = ops.valueAt(j);
-                            if (op.startNesting > 0) {
-                                final long duration = SystemClock.elapsedRealtime()
-                                        - op.startRealtime;
-                                // We don't support proxy long running ops (start/stop)
-                                mHistoricalRegistry.increaseOpAccessDuration(op.op,
-                                        op.uidState.uid, op.packageName, oldPendingState,
-                                        AppOpsManager.OP_FLAG_SELF, duration);
-                                // Finish the op in the old state
-                                op.finished(now, duration, oldPendingState,
-                                        AppOpsManager.OP_FLAG_SELF);
-                                // Start the op in the new state
-                                op.startRealtime = now;
-                                op.started(now, newState, AppOpsManager.OP_FLAG_SELF);
+
+                            int numFeatures = op.mFeatures.size();
+                            for (int featureNum = 0; featureNum < numFeatures;
+                                    featureNum++) {
+                                final FeatureOp featureOp = op.mFeatures.valueAt(
+                                        featureNum);
+                                if (featureOp.startNesting > 0) {
+                                    final long duration = SystemClock.elapsedRealtime()
+                                            - featureOp.startRealtime;
+                                    // We don't support proxy long running ops (start/stop)
+                                    mHistoricalRegistry.increaseOpAccessDuration(op.op,
+                                            op.uidState.uid, op.packageName, oldPendingState,
+                                            AppOpsManager.OP_FLAG_SELF, duration);
+                                    // Finish the op in the old state
+                                    featureOp.finished(now, duration, oldPendingState,
+                                            AppOpsManager.OP_FLAG_SELF);
+                                    // Start the op in the new state
+                                    featureOp.startRealtime = now;
+                                    featureOp.started(now, newState, AppOpsManager.OP_FLAG_SELF);
+                                }
                             }
                         }
                     }
@@ -1069,24 +1162,32 @@
         return resOps;
     }
 
-    private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
-        if (uidOps == null) {
+    @Nullable
+    private ArrayList<AppOpsManager.OpEntry> collectUidOps(@NonNull UidState uidState,
+            @Nullable int[] ops) {
+        if (uidState.opModes == null) {
+            return null;
+        }
+
+        int opModeCount = uidState.opModes.size();
+        if (opModeCount == 0) {
             return null;
         }
         ArrayList<AppOpsManager.OpEntry> resOps = null;
         if (ops == null) {
             resOps = new ArrayList<>();
-            for (int j=0; j<uidOps.size(); j++) {
-                resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
+            for (int i = 0; i < opModeCount; i++) {
+                int code = uidState.opModes.keyAt(i);
+                resOps.add(new OpEntry(code, uidState.opModes.get(code), new Pair[0]));
             }
         } else {
             for (int j=0; j<ops.length; j++) {
-                int index = uidOps.indexOfKey(ops[j]);
-                if (index >= 0) {
+                int code = uidState.opModes.keyAt(j);
+                if (code >= 0) {
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
+                    resOps.add(new OpEntry(code, uidState.opModes.get(code), new Pair[0]));
                 }
             }
         }
@@ -1094,17 +1195,17 @@
     }
 
     private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
-        if (op.running) {
-            op.continuing(elapsedNow - op.startRealtime,
-                op.uidState.state, AppOpsManager.OP_FLAG_SELF);
+        final int numFeatures = op.mFeatures.size();
+
+        for (int i = 0; i < numFeatures; i++) {
+            final FeatureOp featureOp = op.mFeatures.valueAt(i);
+            if (featureOp.running) {
+                featureOp.continuing(elapsedNow - featureOp.startRealtime,
+                        op.uidState.state, AppOpsManager.OP_FLAG_SELF);
+            }
         }
-        final OpEntry entry = new OpEntry(op.op, op.running, op.mode,
-            op.mAccessTimes != null ? op.mAccessTimes.clone() : null,
-            op.mRejectTimes != null ? op.mRejectTimes.clone() : null,
-            op.mDurations != null ? op.mDurations.clone() : null,
-            op.mProxyUids != null ? op.mProxyUids.clone() : null,
-            op.mProxyPackageNames != null ? op.mProxyPackageNames.clone() : null);
-        return entry;
+
+        return op.createEntryLocked();
     }
 
     @Override
@@ -1232,7 +1333,7 @@
             if (uidState == null) {
                 return null;
             }
-            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
+            ArrayList<AppOpsManager.OpEntry> resOps = collectUidOps(uidState, ops);
             if (resOps == null) {
                 return null;
             }
@@ -1245,8 +1346,11 @@
     }
 
     private void pruneOpLocked(Op op, int uid, String packageName) {
-        if (!op.hasAnyTime()) {
-            Ops ops = getOpsRawLocked(uid, packageName, false /* isPrivileged */, false /* edit */);
+        op.removeFeaturesWithNoTime();
+
+        if (op.mFeatures.size() == 0) {
+            Ops ops = getOpsRawLocked(uid, packageName, false /* isPrivileged */,
+                    false /* edit */);
             if (ops != null) {
                 ops.remove(op.op);
                 if (ops.size() <= 0) {
@@ -1569,9 +1673,9 @@
         if (uid != UID_ANY && callback.mWatchingUid >= 0 && callback.mWatchingUid != uid) {
             return;
         }
-        // There are components watching for mode changes such as window manager
+        // There are features watching for mode changes such as window manager
         // and location manager which are in our process. The callbacks in these
-        // components may require permissions our remote caller does not have.
+        // features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
         try {
             callback.mCallback.opChanged(code, uid, packageName);
@@ -1706,7 +1810,9 @@
                                     mOpModeWatchers.get(curOp.op));
                             callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
                                     mPackageModeWatchers.get(packageName));
-                            if (!curOp.hasAnyTime()) {
+
+                            curOp.removeFeaturesWithNoTime();
+                            if (curOp.mFeatures.size() == 0) {
                                 pkgOps.removeAt(j);
                             }
                         }
@@ -1989,8 +2095,9 @@
     }
 
     @Override
-    public int noteProxyOperation(int code, int proxyUid,
-            String proxyPackageName, int proxiedUid, String proxiedPackageName) {
+    public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
+            String proxiedFeatureId, int proxyUid, String proxyPackageName,
+            String proxyFeatureId) {
         verifyIncomingUid(proxyUid);
         verifyIncomingOp(code);
 
@@ -2005,8 +2112,8 @@
 
         final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
-        final int proxyMode = noteOperationUnchecked(code, proxyUid,
-                resolveProxyPackageName, Process.INVALID_UID, null, proxyFlags);
+        final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
+                proxyFeatureId, Process.INVALID_UID, null, null, proxyFlags);
         if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
             return proxyMode;
         }
@@ -2018,35 +2125,39 @@
         final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
                 : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
         return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
-                proxyUid, resolveProxyPackageName, proxiedFlags);
+                proxiedFeatureId, proxyUid, resolveProxyPackageName, proxyFeatureId,
+                proxiedFlags);
     }
 
     @Override
-    public int noteOperation(int code, int uid, String packageName) {
+    public int noteOperation(int code, int uid, String packageName, String featureId) {
         final CheckOpsDelegate delegate;
         synchronized (this) {
             delegate = mCheckOpsDelegate;
         }
         if (delegate == null) {
-            return noteOperationImpl(code, uid, packageName);
+            return noteOperationImpl(code, uid, packageName, featureId);
         }
-        return delegate.noteOperation(code, uid, packageName,
+        return delegate.noteOperation(code, uid, packageName, featureId,
                 AppOpsService.this::noteOperationImpl);
     }
 
-    private int noteOperationImpl(int code, int uid, String packageName) {
+    private int noteOperationImpl(int code, int uid, String packageName, String featureId) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
         String resolvedPackageName = resolvePackageName(uid, packageName);
         if (resolvedPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
         }
-        return noteOperationUnchecked(code, uid, resolvedPackageName, Process.INVALID_UID, null,
-                AppOpsManager.OP_FLAG_SELF);
+        return noteOperationUnchecked(code, uid, resolvedPackageName, featureId,
+                Process.INVALID_UID, null, null, AppOpsManager.OP_FLAG_SELF);
     }
 
-    private int noteOperationUnchecked(int code, int uid, String packageName,
-            int proxyUid, String proxyPackageName, @OpFlags int flags) {
+    private int noteOperationUnchecked(int code, int uid, String packageName, String featureId,
+            int proxyUid, String proxyPackageName, @Nullable String proxyFeatureId,
+            @OpFlags int flags) {
+        // TODO moltmann: Verify that feature is declared in package
+
         boolean isPrivileged;
         try {
             isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
@@ -2065,15 +2176,18 @@
                 return AppOpsManager.MODE_ERRORED;
             }
             final Op op = getOpLocked(ops, code, true);
+            final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
             if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
                 scheduleOpNotedIfNeededLocked(code, uid, packageName,
                         AppOpsManager.MODE_IGNORED);
                 return AppOpsManager.MODE_IGNORED;
             }
             final UidState uidState = ops.uidState;
-            if (op.running) {
-                final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
-                    op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+            if (featureOp.running) {
+                final OpFeatureEntry entry = getOpLocked(ops, code,
+                        false).createSingleFeatureEntryLocked(featureId).getFeatures().get(
+                        featureId);
+
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
                         + " code " + code + " time=" + entry.getLastAccessTime(uidState.state,
                         uidState.state, flags) + " duration=" + entry.getLastDuration(
@@ -2089,8 +2203,8 @@
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
-                            uidState.state, flags);
+                    featureOp.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                            proxyFeatureId, uidState.state, flags);
                     mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
                             uidState.state, flags);
                     scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
@@ -2103,8 +2217,8 @@
                     if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
-                            uidState.state, flags);
+                    featureOp.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                            proxyFeatureId, uidState.state, flags);
                     mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
                             uidState.state, flags);
                     scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
@@ -2112,9 +2226,10 @@
                 }
             }
             if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
-                    + " package " + packageName);
-            op.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
-                    uidState.state, flags);
+                    + " package " + packageName + (featureId == null ? "" : "." + featureId));
+            featureOp.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                    proxyFeatureId, uidState.state, flags);
+            // TODO moltmann: Add features to historical app-ops
             mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
                     uidState.state, flags);
             scheduleOpNotedIfNeededLocked(code, uid, packageName,
@@ -2123,6 +2238,7 @@
         }
     }
 
+    // TODO moltmann: Allow watching for feature ops
     @Override
     public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
         int watchedUid = -1;
@@ -2216,7 +2332,7 @@
 
     @Override
     public void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
-            String message) {
+            String featureId, String message) {
         Preconditions.checkNotNull(message);
         Preconditions.checkNotNull(packageName);
         verifyAndGetIsPrivileged(uid, packageName);
@@ -2238,7 +2354,7 @@
 
                 RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
                 AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid,
-                        callingPackageName, message, now);
+                        callingPackageName, featureId, message, now);
                 final boolean[] wasNoteForwarded = {false};
 
                 if (callbacks != null) {
@@ -2249,7 +2365,7 @@
                         } catch (RemoteException e) {
                             Slog.e(TAG,
                                     "Could not forward noteOp of " + opCode + " to " + packageName
-                                            + "/" + uid, e);
+                                            + "/" + uid + "(" + featureId + ")", e);
                         }
                     });
                 }
@@ -2351,7 +2467,7 @@
 
     @Override
     public int startOperation(IBinder token, int code, int uid, String packageName,
-            boolean startIfModeDefault) {
+            String featureId, boolean startIfModeDefault) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
         String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -2380,6 +2496,7 @@
             if (isOpRestrictedLocked(uid, code, resolvedPackageName, isPrivileged)) {
                 return AppOpsManager.MODE_IGNORED;
             }
+            final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
             final int switchCode = AppOpsManager.opToSwitch(code);
             final UidState uidState = ops.uidState;
             // If there is a non-default per UID policy (we set UID op mode only if
@@ -2393,8 +2510,9 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
                     // We don't support proxy long running ops (start/stop)
-                    op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
-                            null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
+                    featureOp.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
+                            null /*proxyPackage*/, null, uidState.state,
+                            AppOpsManager.OP_FLAG_SELF);
                     mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
                             uidState.state, AppOpsManager.OP_FLAG_SELF);
                     return uidMode;
@@ -2408,8 +2526,9 @@
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
                     // We don't support proxy long running ops (start/stop)
-                    op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
-                            null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
+                    featureOp.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
+                            null /*proxyPackage*/, null, uidState.state,
+                            AppOpsManager.OP_FLAG_SELF);
                     mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
                             uidState.state, AppOpsManager.OP_FLAG_SELF);
                     return mode;
@@ -2417,28 +2536,30 @@
             }
             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + resolvedPackageName);
-            if (op.startNesting == 0) {
-                op.startRealtime = SystemClock.elapsedRealtime();
+            if (featureOp.startNesting == 0) {
+                featureOp.startRealtime = SystemClock.elapsedRealtime();
                 // We don't support proxy long running ops (start/stop)
-                op.started(System.currentTimeMillis(), uidState.state,
+                featureOp.started(System.currentTimeMillis(), uidState.state,
                         AppOpsManager.OP_FLAG_SELF);
                 mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName,
                         uidState.state, AppOpsManager.OP_FLAG_SELF);
 
-                scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
+                // TODO moltmann: call back when a feature became inactive
+                if (uidState.startNesting == 0) {
+                    scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
+                }
             }
-            op.startNesting++;
+            featureOp.startNesting++;
             uidState.startNesting++;
-            if (client.mStartedOps != null) {
-                client.mStartedOps.add(op);
-            }
+            client.mStartedOps.add(new Pair<>(op, featureId));
         }
 
         return AppOpsManager.MODE_ALLOWED;
     }
 
     @Override
-    public void finishOperation(IBinder token, int code, int uid, String packageName) {
+    public void finishOperation(IBinder token, int code, int uid, String packageName,
+            String featureId) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
         String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -2463,9 +2584,16 @@
             if (op == null) {
                 return;
             }
-            if (client.mStartedOps.remove(op)) {
-                finishOperationLocked(op, /*finishNested*/ false);
-                if (op.startNesting <= 0) {
+            final FeatureOp featureOp = op.mFeatures.get(featureId);
+            if (featureOp == null) {
+                return;
+            }
+
+            if (client.mStartedOps.remove(new Pair<>(op, featureId))) {
+                finishOperationLocked(op, featureId, /*finishNested*/ false);
+
+                // TODO moltmann: call back when a feature became inactive
+                if (op.uidState.startNesting <= 0) {
                     scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
                 }
 
@@ -2520,9 +2648,9 @@
 
     private void notifyOpActiveChanged(ArraySet<ActiveCallback> callbacks,
             int code, int uid, String packageName, boolean active) {
-        // There are components watching for mode changes such as window manager
+        // There are features watching for mode changes such as window manager
         // and location manager which are in our process. The callbacks in these
-        // components may require permissions our remote caller does not have.
+        // features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
         try {
             final int callbackCount = callbacks.size();
@@ -2566,8 +2694,8 @@
 
     private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
             int code, int uid, String packageName, int result) {
-        // There are components watching for checks in our process. The callbacks in
-        // these components may require permissions our remote caller does not have.
+        // There are features watching for checks in our process. The callbacks in
+        // these features may require permissions our remote caller does not have.
         final long identity = Binder.clearCallingIdentity();
         try {
             final int callbackCount = callbacks.size();
@@ -2611,32 +2739,34 @@
         return permInfo.getProtection() == PROTECTION_DANGEROUS;
     }
 
-    void finishOperationLocked(Op op, boolean finishNested) {
-        final int opCode = op.op;
-        final int uid = op.uidState.uid;
-        if (op.startNesting <= 1 || finishNested) {
-            if (op.startNesting == 1 || finishNested) {
+    void finishOperationLocked(@NonNull Op op, @Nullable String featureId, boolean finishNested) {
+        final FeatureOp featureOp = op.mFeatures.get(featureId);
+        final int opCode = featureOp.parent.op;
+        final int uid = featureOp.parent.uidState.uid;
+        if (featureOp.startNesting <= 1 || finishNested) {
+            if (featureOp.startNesting == 1 || finishNested) {
                 // We don't support proxy long running ops (start/stop)
-                final long duration = SystemClock.elapsedRealtime() - op.startRealtime;
-                op.finished(System.currentTimeMillis(), duration, op.uidState.state,
+                final long duration = SystemClock.elapsedRealtime() - featureOp.startRealtime;
+                featureOp.finished(System.currentTimeMillis(), duration, op.uidState.state,
                         AppOpsManager.OP_FLAG_SELF);
                 mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName,
                         op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration);
             } else {
-                final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
-                    op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+                final OpFeatureEntry entry = op.createSingleFeatureEntryLocked(
+                        featureId).getFeatures().get(featureId);
                 Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg "
                         + op.packageName + " code " + opCode + " time="
                         + entry.getLastAccessTime(OP_FLAGS_ALL)
                         + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE,
-                        MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting=" + op.startNesting);
+                        MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting="
+                        + featureOp.startNesting);
             }
-            if (op.startNesting >= 1) {
-                op.uidState.startNesting -= op.startNesting;
+            if (featureOp.startNesting >= 1) {
+                op.uidState.startNesting -= featureOp.startNesting;
             }
-            op.startNesting = 0;
+            featureOp.startNesting = 0;
         } else {
-            op.startNesting--;
+            featureOp.startNesting--;
             op.uidState.startNesting--;
         }
     }
@@ -3170,9 +3300,36 @@
         uidState.evalForegroundOps(mOpModeWatchers);
     }
 
+    private void readFeatureOp(XmlPullParser parser, @NonNull Op parent,
+            @Nullable String feature) throws NumberFormatException, IOException {
+        final FeatureOp featureOp = parent.getOrCreateFeature(parent, feature);
+
+        final long key = XmlUtils.readLongAttribute(parser, "n");
+
+        final int flags = AppOpsManager.extractFlagsFromKey(key);
+        final int state = AppOpsManager.extractUidStateFromKey(key);
+
+        final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
+        final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
+        final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
+        final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
+        final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
+        final String proxyFeatureId = XmlUtils.readStringAttribute(parser, "pc");
+
+        if (accessTime > 0) {
+            featureOp.accessed(accessTime, proxyUid, proxyPkg, proxyFeatureId, state, flags);
+        }
+        if (rejectTime > 0) {
+            featureOp.rejected(rejectTime, proxyUid, proxyPkg, proxyFeatureId, state, flags);
+        }
+        if (accessDuration > 0) {
+            featureOp.running(accessTime, accessDuration, state, flags);
+        }
+    }
+
     private void readOp(XmlPullParser parser, @NonNull UidState uidState,
-            @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
-            XmlPullParserException, IOException {
+        @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
+        XmlPullParserException, IOException {
         Op op = new Op(uidState, pkgName,
                 Integer.parseInt(parser.getAttributeValue(null, "n")));
 
@@ -3189,26 +3346,7 @@
             }
             String tagName = parser.getName();
             if (tagName.equals("st")) {
-                final long key = XmlUtils.readLongAttribute(parser, "n");
-
-                final int flags = AppOpsManager.extractFlagsFromKey(key);
-                final int state = AppOpsManager.extractUidStateFromKey(key);
-
-                final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
-                final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
-                final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
-                final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
-                final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
-
-                if (accessTime > 0) {
-                    op.accessed(accessTime, proxyUid, proxyPkg, state, flags);
-                }
-                if (rejectTime > 0) {
-                    op.rejected(rejectTime, proxyUid, proxyPkg, state, flags);
-                }
-                if (accessDuration > 0) {
-                    op.running(accessTime, accessDuration, state, flags);
-                }
+                readFeatureOp(parser, op, XmlUtils.readStringAttribute(parser, "id"));
             } else {
                 Slog.w(TAG, "Unknown element under <op>: "
                         + parser.getName());
@@ -3323,51 +3461,64 @@
                                 out.attribute(null, "m", Integer.toString(op.getMode()));
                             }
 
-                            final LongSparseArray keys = op.collectKeys();
-                            if (keys == null || keys.size() <= 0) {
-                                out.endTag(null, "op");
-                                continue;
-                            }
+                            for (String featureId : op.getFeatures().keySet()) {
+                                final OpFeatureEntry feature = op.getFeatures().get(
+                                        featureId);
 
-                            final int keyCount = keys.size();
-                            for (int k = 0; k < keyCount; k++) {
-                                final long key = keys.keyAt(k);
-
-                                final int uidState = AppOpsManager.extractUidStateFromKey(key);
-                                final int flags = AppOpsManager.extractFlagsFromKey(key);
-
-                                final long accessTime = op.getLastAccessTime(
-                                        uidState, uidState, flags);
-                                final long rejectTime = op.getLastRejectTime(
-                                        uidState, uidState, flags);
-                                final long accessDuration = op.getLastDuration(
-                                        uidState, uidState, flags);
-                                final String proxyPkg = op.getProxyPackageName(uidState, flags);
-                                final int proxyUid = op.getProxyUid(uidState, flags);
-
-                                if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
-                                        && proxyPkg == null && proxyUid < 0) {
+                                final LongSparseArray keys = feature.collectKeys();
+                                if (keys == null || keys.size() <= 0) {
                                     continue;
                                 }
+                                final int keyCount = keys.size();
 
-                                out.startTag(null, "st");
-                                out.attribute(null, "n", Long.toString(key));
-                                if (accessTime > 0) {
-                                    out.attribute(null, "t", Long.toString(accessTime));
+                                for (int k = 0; k < keyCount; k++) {
+                                    final long key = keys.keyAt(k);
+
+                                    final int uidState = AppOpsManager.extractUidStateFromKey(key);
+                                    final int flags = AppOpsManager.extractFlagsFromKey(key);
+
+                                    final long accessTime = feature.getLastAccessTime(
+                                            uidState, uidState, flags);
+                                    final long rejectTime = feature.getLastRejectTime(
+                                            uidState, uidState, flags);
+                                    final long accessDuration = feature.getLastDuration(
+                                            uidState, uidState, flags);
+                                    final String proxyPkg = feature.getProxyPackageName(uidState,
+                                            flags);
+                                    final String proxyFeatureId = feature.getProxyFeatureId(
+                                            uidState, flags);
+                                    final int proxyUid = feature.getProxyUid(uidState, flags);
+
+                                    if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
+                                            && proxyPkg == null && proxyUid < 0) {
+                                        continue;
+                                    }
+
+                                    out.startTag(null, "st");
+                                    if (featureId != null) {
+                                        out.attribute(null, "id", featureId);
+                                    }
+                                    out.attribute(null, "n", Long.toString(key));
+                                    if (accessTime > 0) {
+                                        out.attribute(null, "t", Long.toString(accessTime));
+                                    }
+                                    if (rejectTime > 0) {
+                                        out.attribute(null, "r", Long.toString(rejectTime));
+                                    }
+                                    if (accessDuration > 0) {
+                                        out.attribute(null, "d", Long.toString(accessDuration));
+                                    }
+                                    if (proxyPkg != null) {
+                                        out.attribute(null, "pp", proxyPkg);
+                                    }
+                                    if (proxyFeatureId != null) {
+                                        out.attribute(null, "pc", proxyFeatureId);
+                                    }
+                                    if (proxyUid >= 0) {
+                                        out.attribute(null, "pu", Integer.toString(proxyUid));
+                                    }
+                                    out.endTag(null, "st");
                                 }
-                                if (rejectTime > 0) {
-                                    out.attribute(null, "r", Long.toString(rejectTime));
-                                }
-                                if (accessDuration > 0) {
-                                    out.attribute(null, "d", Long.toString(accessDuration));
-                                }
-                                if (proxyPkg != null) {
-                                    out.attribute(null, "pp", proxyPkg);
-                                }
-                                if (proxyUid >= 0) {
-                                    out.attribute(null, "pu", Integer.toString(proxyUid));
-                                }
-                                out.endTag(null, "st");
                             }
 
                             out.endTag(null, "op");
@@ -3395,6 +3546,7 @@
 
         int userId = UserHandle.USER_SYSTEM;
         String packageName;
+        String featureId;
         String opStr;
         String modeStr;
         int op;
@@ -3499,6 +3651,8 @@
                     userId = UserHandle.parseUserArg(getNextArgRequired());
                 } else if ("--uid".equals(argument)) {
                     targetsUid = true;
+                } else if ("--feature".equals(argument)) {
+                    featureId = getNextArgRequired();
                 } else {
                     if (packageName == null) {
                         packageName = argument;
@@ -3593,13 +3747,13 @@
         pw.println("AppOps service (appops) commands:");
         pw.println("  help");
         pw.println("    Print this help text.");
-        pw.println("  start [--user <USER_ID>] <PACKAGE | UID> <OP> ");
+        pw.println("  start [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> <OP> ");
         pw.println("    Starts a given operation for a particular application.");
-        pw.println("  stop [--user <USER_ID>] <PACKAGE | UID> <OP> ");
+        pw.println("  stop [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> <OP> ");
         pw.println("    Stops a given operation for a particular application.");
         pw.println("  set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>");
         pw.println("    Set the mode for a particular application and operation.");
-        pw.println("  get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
+        pw.println("  get [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> [<OP>]");
         pw.println("    Return the mode for a particular application and optional operation.");
         pw.println("  query-op [--user <USER_ID>] <OP> [<MODE>]");
         pw.println("    Print all packages that currently have the given op in the given mode.");
@@ -3703,21 +3857,45 @@
                             pw.print(AppOpsManager.opToName(ent.getOp()));
                             pw.print(": ");
                             pw.print(AppOpsManager.modeToName(ent.getMode()));
-                            if (ent.getTime() != 0) {
-                                pw.print("; time=");
-                                TimeUtils.formatDuration(now - ent.getTime(), pw);
-                                pw.print(" ago");
-                            }
-                            if (ent.getRejectTime() != 0) {
-                                pw.print("; rejectTime=");
-                                TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
-                                pw.print(" ago");
-                            }
-                            if (ent.getDuration() == -1) {
-                                pw.print(" (running)");
-                            } else if (ent.getDuration() != 0) {
-                                pw.print("; duration=");
-                                TimeUtils.formatDuration(ent.getDuration(), pw);
+                            if (shell.featureId == null) {
+                                if (ent.getTime() != 0) {
+                                    pw.print("; time=");
+                                    TimeUtils.formatDuration(now - ent.getTime(), pw);
+                                    pw.print(" ago");
+                                }
+                                if (ent.getRejectTime() != 0) {
+                                    pw.print("; rejectTime=");
+                                    TimeUtils.formatDuration(now - ent.getRejectTime(), pw);
+                                    pw.print(" ago");
+                                }
+                                if (ent.getDuration() == -1) {
+                                    pw.print(" (running)");
+                                } else if (ent.getDuration() != 0) {
+                                    pw.print("; duration=");
+                                    TimeUtils.formatDuration(ent.getDuration(), pw);
+                                }
+                            } else {
+                                final OpFeatureEntry featureEnt = ent.getFeatures().get(
+                                        shell.featureId);
+                                if (featureEnt != null) {
+                                    if (featureEnt.getTime() != 0) {
+                                        pw.print("; time=");
+                                        TimeUtils.formatDuration(now - featureEnt.getTime(), pw);
+                                        pw.print(" ago");
+                                    }
+                                    if (featureEnt.getRejectTime() != 0) {
+                                        pw.print("; rejectTime=");
+                                        TimeUtils.formatDuration(now - featureEnt.getRejectTime(),
+                                                pw);
+                                        pw.print(" ago");
+                                    }
+                                    if (featureEnt.getDuration() == -1) {
+                                        pw.print(" (running)");
+                                    } else if (featureEnt.getDuration() != 0) {
+                                        pw.print("; duration=");
+                                        TimeUtils.formatDuration(featureEnt.getDuration(), pw);
+                                    }
+                                }
                             }
                             pw.println();
                         }
@@ -3822,8 +4000,8 @@
                     }
 
                     if (shell.packageName != null) {
-                        shell.mInterface.startOperation(shell.mToken,
-                                shell.op, shell.packageUid, shell.packageName, true);
+                        shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid,
+                                shell.packageName, shell.featureId, true);
                     } else {
                         return -1;
                     }
@@ -3837,7 +4015,7 @@
 
                     if (shell.packageName != null) {
                         shell.mInterface.finishOperation(shell.mToken,
-                                shell.op, shell.packageUid, shell.packageName);
+                                shell.op, shell.packageUid, shell.packageName, shell.featureId);
                     } else {
                         return -1;
                     }
@@ -3868,11 +4046,23 @@
         pw.println("    Output the historical data.");
     }
 
-    private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op,
+    private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op,
             long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
+        final int numFeatures = op.mFeatures.size();
+        for (int i = 0; i < numFeatures; i++) {
+            pw.print(prefix + op.mFeatures.keyAt(i) + "=[\n");
+            dumpStatesLocked(pw, nowElapsed, op, op.mFeatures.keyAt(i), now, sdf, date,
+                    prefix + "  ");
+            pw.print(prefix + "]\n");
+        }
+    }
 
-        final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
-            op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+    private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op,
+            @Nullable String featureId, long now, @NonNull SimpleDateFormat sdf,
+            @NonNull Date date, @NonNull String prefix) {
+
+        final OpFeatureEntry entry = op.createSingleFeatureEntryLocked(
+                featureId).getFeatures().get(featureId);
 
         final LongSparseArray keys = entry.collectKeys();
         if (keys == null || keys.size() <= 0) {
@@ -3893,6 +4083,7 @@
             final long accessDuration = entry.getLastDuration(
                     uidState, uidState, flags);
             final String proxyPkg = entry.getProxyPackageName(uidState, flags);
+            final String proxyFeatureId = entry.getProxyFeatureId(uidState, flags);
             final int proxyUid = entry.getProxyUid(uidState, flags);
 
             if (accessTime > 0) {
@@ -3915,6 +4106,8 @@
                     pw.print(proxyUid);
                     pw.print(", pkg=");
                     pw.print(proxyPkg);
+                    pw.print(", feature=");
+                    pw.print(proxyFeatureId);
                     pw.print("]");
                 }
                 pw.println();
@@ -3935,11 +4128,24 @@
                     pw.print(proxyUid);
                     pw.print(", pkg=");
                     pw.print(proxyPkg);
+                    pw.print(", feature=");
+                    pw.print(proxyFeatureId);
                     pw.print("]");
                 }
                 pw.println();
             }
         }
+
+        final FeatureOp featureOp = op.mFeatures.get(featureId);
+        if (featureOp.running) {
+            pw.print(prefix + "Running start at: ");
+            TimeUtils.formatDuration(nowElapsed - featureOp.startRealtime, pw);
+            pw.println();
+        }
+        if (featureOp.startNesting != 0) {
+            pw.print(prefix + "startNesting=");
+            pw.println(featureOp.startNesting);
+        }
     }
 
     @Override
@@ -4195,7 +4401,8 @@
                     if (cs.mStartedOps.size() > 0) {
                         boolean printedStarted = false;
                         for (int j=0; j<cs.mStartedOps.size(); j++) {
-                            Op op = cs.mStartedOps.get(j);
+                            final Pair<Op, String> startedOp = cs.mStartedOps.get(j);
+                            final Op op = startedOp.first;
                             if (dumpOp >= 0 && op.op != dumpOp) {
                                 continue;
                             }
@@ -4217,6 +4424,7 @@
                             }
                             pw.print("        "); pw.print("uid="); pw.print(op.uidState.uid);
                             pw.print(" pkg="); pw.print(op.packageName);
+                            pw.print(" featureId="); pw.print(startedOp.second);
                             pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
                         }
                     }
@@ -4363,16 +4571,7 @@
                             pw.print("="); pw.print(AppOpsManager.modeToName(mode));
                         }
                         pw.println("): ");
-                        dumpStatesLocked(pw, op, now, sdf, date, "          ");
-                        if (op.running) {
-                            pw.print("          Running start at: ");
-                            TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw);
-                            pw.println();
-                        }
-                        if (op.startNesting != 0) {
-                            pw.print("          startNesting=");
-                            pw.println(op.startNesting);
-                        }
+                        dumpStatesLocked(pw, nowElapsed, op, now, sdf, date, "        ");
                     }
                 }
             }
@@ -4575,12 +4774,15 @@
         if (resolvedPackageName == null) {
             return false;
         }
+        // TODO moltmann: Allow to check for feature op activeness
         synchronized (AppOpsService.this) {
             for (int i = mClients.size() - 1; i >= 0; i--) {
                 final ClientState client = mClients.valueAt(i);
                 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) {
-                    final Op op = client.mStartedOps.get(j);
-                    if (op.op == code && op.uidState.uid == uid) return true;
+                    final Pair<Op, String> startedOp = client.mStartedOps.get(j);
+                    if (startedOp.first.op == code && startedOp.first.uidState.uid == uid) {
+                        return true;
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
index 1a5dac5..e9d2b31 100644
--- a/services/core/java/com/android/server/appop/TEST_MAPPING
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -18,6 +18,23 @@
                     "include-filter": "com.android.server.appop"
                 }
             ]
+        },
+        {
+            "name": "CtsPermissionTestCases",
+            "options": [
+                {
+                    "include-filter": "android.permission.cts.BackgroundPermissionsTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.SplitPermissionTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.PermissionFlagsTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.SharedUidPermissionsTest"
+                }
+            ]
         }
     ]
 }
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 087c84f..67d3589 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -23,7 +23,6 @@
 import android.Manifest;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
-import android.app.ActivityManager;
 import android.attention.AttentionManagerInternal;
 import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
 import android.content.BroadcastReceiver;
@@ -300,7 +299,8 @@
     @GuardedBy("mLock")
     @VisibleForTesting
     protected UserState getOrCreateCurrentUserStateLocked() {
-        return getOrCreateUserStateLocked(ActivityManager.getCurrentUser());
+        // Doesn't need to cache the states of different users.
+        return getOrCreateUserStateLocked(0);
     }
 
     @GuardedBy("mLock")
@@ -318,7 +318,8 @@
     @Nullable
     @VisibleForTesting
     protected UserState peekCurrentUserStateLocked() {
-        return peekUserStateLocked(ActivityManager.getCurrentUser());
+        // Doesn't need to cache the states of different users.
+        return peekUserStateLocked(0);
     }
 
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a6ac17d..0d493b8 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1018,7 +1018,14 @@
 
         synchronized (mAudioPolicies) {
             for (AudioPolicyProxy policy : mAudioPolicies.values()) {
-                policy.connectMixes();
+                final int status = policy.connectMixes();
+                if (status != AudioSystem.SUCCESS) {
+                    // note that PERMISSION_DENIED may also indicate trouble getting to APService
+                    Log.e(TAG, "onAudioServerDied: error "
+                            + AudioSystem.audioSystemErrorToString(status)
+                            + " when connecting mixes for policy " + policy.toLogFriendlyString());
+                    policy.release();
+                }
             }
         }
 
@@ -7019,16 +7026,8 @@
         }
 
         public void binderDied() {
-            synchronized (mAudioPolicies) {
-                Log.i(TAG, "audio policy " + mPolicyCallback + " died");
-                release();
-                mAudioPolicies.remove(mPolicyCallback.asBinder());
-            }
-            if (mIsVolumeController) {
-                synchronized (mExtVolumeControllerLock) {
-                    mExtVolumeController = null;
-                }
-            }
+            Log.i(TAG, "audio policy " + mPolicyCallback + " died");
+            release();
         }
 
         String getRegistrationId() {
@@ -7052,9 +7051,20 @@
                     Log.e(TAG, "Fail to unregister Audiopolicy callback from MediaProjection");
                 }
             }
+            if (mIsVolumeController) {
+                synchronized (mExtVolumeControllerLock) {
+                    mExtVolumeController = null;
+                }
+            }
             final long identity = Binder.clearCallingIdentity();
             AudioSystem.registerPolicyMixes(mMixes, false);
             Binder.restoreCallingIdentity(identity);
+            synchronized (mAudioPolicies) {
+                mAudioPolicies.remove(mPolicyCallback.asBinder());
+            }
+            try {
+                mPolicyCallback.notifyUnregistration();
+            } catch (RemoteException e) { }
         }
 
         boolean hasMixAffectingUsage(int usage, int excludedFlags) {
@@ -7105,7 +7115,7 @@
             }
         }
 
-        int connectMixes() {
+        @AudioSystem.AudioSystemError int connectMixes() {
             final long identity = Binder.clearCallingIdentity();
             int status = AudioSystem.registerPolicyMixes(mMixes, true);
             Binder.restoreCallingIdentity(identity);
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java
similarity index 100%
rename from core/java/com/android/server/backup/SystemBackupAgent.java
rename to services/core/java/com/android/server/backup/SystemBackupAgent.java
diff --git a/core/java/com/android/server/backup/UsageStatsBackupHelper.java b/services/core/java/com/android/server/backup/UsageStatsBackupHelper.java
similarity index 100%
rename from core/java/com/android/server/backup/UsageStatsBackupHelper.java
rename to services/core/java/com/android/server/backup/UsageStatsBackupHelper.java
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 4f1db3c..44c81fc 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -37,13 +37,12 @@
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.IBiometricAuthenticator;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricService;
 import android.hardware.biometrics.IBiometricServiceReceiver;
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
-import android.hardware.face.FaceManager;
 import android.hardware.face.IFaceService;
-import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.IFingerprintService;
 import android.net.Uri;
 import android.os.Binder;
@@ -68,6 +67,8 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.server.SystemService;
+import com.android.server.biometrics.face.FaceAuthenticator;
+import com.android.server.biometrics.fingerprint.FingerprintAuthenticator;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -95,11 +96,6 @@
     private static final int MSG_CANCEL_AUTHENTICATION = 10;
     private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
     private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
-    private static final int[] FEATURE_ID = {
-        TYPE_FINGERPRINT,
-        TYPE_IRIS,
-        TYPE_FACE
-    };
 
     /**
      * Authentication either just called and we have not transitioned to the CALLED state, or
@@ -172,7 +168,7 @@
         byte[] mTokenEscrow;
         // Waiting for SystemUI to complete animation
         int mErrorEscrow;
-        String mErrorStringEscrow;
+        int mVendorCodeEscrow;
 
         // Timestamp when authentication started
         private long mStartTimeMs;
@@ -219,19 +215,15 @@
     private final Injector mInjector;
     @VisibleForTesting
     final IBiometricService.Stub mImpl;
+    private final boolean mHasFeatureFace;
     private final boolean mHasFeatureFingerprint;
     private final boolean mHasFeatureIris;
-    private final boolean mHasFeatureFace;
     @VisibleForTesting
     final SettingObserver mSettingObserver;
     private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks;
     private final Random mRandom = new Random();
 
     @VisibleForTesting
-    IFingerprintService mFingerprintService;
-    @VisibleForTesting
-    IFaceService mFaceService;
-    @VisibleForTesting
     IStatusBarService mStatusBarService;
     @VisibleForTesting
     KeyStore mKeyStore;
@@ -262,7 +254,7 @@
                 }
 
                 case MSG_ON_AUTHENTICATION_REJECTED: {
-                    handleAuthenticationRejected((String) msg.obj /* failureReason */);
+                    handleAuthenticationRejected();
                     break;
                 }
 
@@ -270,8 +262,9 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     handleOnError(
                             args.argi1 /* cookie */,
-                            args.argi2 /* error */,
-                            (String) args.arg1 /* message */);
+                            args.argi2 /* modality */,
+                            args.argi3 /* error */,
+                            args.argi4 /* vendorCode */);
                     args.recycle();
                     break;
                 }
@@ -331,7 +324,12 @@
                 }
 
                 case MSG_ON_AUTHENTICATION_TIMED_OUT: {
-                    handleAuthenticationTimedOut((String) msg.obj /* errorMessage */);
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    handleAuthenticationTimedOut(
+                            args.argi1 /* modality */,
+                            args.argi2 /* error */,
+                            args.argi3 /* vendorCode */);
+                    args.recycle();
                     break;
                 }
 
@@ -347,21 +345,23 @@
         }
     };
 
-    private final class AuthenticatorWrapper {
-        final int mType;
-        final BiometricAuthenticator mAuthenticator;
+    /**
+     * Wraps IBiometricAuthenticator implementation and stores information about the authenticator.
+     * TODO(b/141025588): Consider refactoring the tests to not rely on this implementation detail.
+     */
+    @VisibleForTesting
+    public static final class AuthenticatorWrapper {
+        public final int id;
+        public final int strength;
+        public final int modality;
+        public final IBiometricAuthenticator impl;
 
-        AuthenticatorWrapper(int type, BiometricAuthenticator authenticator) {
-            mType = type;
-            mAuthenticator = authenticator;
-        }
-
-        int getType() {
-            return mType;
-        }
-
-        BiometricAuthenticator getAuthenticator() {
-            return mAuthenticator;
+        AuthenticatorWrapper(int id, int strength, int modality,
+                IBiometricAuthenticator impl) {
+            this.id = id;
+            this.strength = strength;
+            this.modality = modality;
+            this.impl = impl;
         }
     }
 
@@ -521,23 +521,28 @@
         @Override
         public void onAuthenticationFailed()
                 throws RemoteException {
-            String failureReason = getContext().getString(R.string.biometric_not_recognized);
-            Slog.v(TAG, "onAuthenticationFailed: " + failureReason);
-            mHandler.obtainMessage(MSG_ON_AUTHENTICATION_REJECTED, failureReason).sendToTarget();
+            Slog.v(TAG, "onAuthenticationFailed");
+            mHandler.obtainMessage(MSG_ON_AUTHENTICATION_REJECTED).sendToTarget();
         }
 
         @Override
-        public void onError(int cookie, int error, String message) throws RemoteException {
+        public void onError(int cookie, int modality, int error, int vendorCode)
+                throws RemoteException {
             // Determine if error is hard or soft error. Certain errors (such as TIMEOUT) are
             // soft errors and we should allow the user to try authenticating again instead of
             // dismissing BiometricPrompt.
             if (error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) {
-                mHandler.obtainMessage(MSG_ON_AUTHENTICATION_TIMED_OUT, message).sendToTarget();
+                SomeArgs args = SomeArgs.obtain();
+                args.argi1 = modality;
+                args.argi2 = error;
+                args.argi3 = vendorCode;
+                mHandler.obtainMessage(MSG_ON_AUTHENTICATION_TIMED_OUT, args).sendToTarget();
             } else {
                 SomeArgs args = SomeArgs.obtain();
                 args.argi1 = cookie;
-                args.argi2 = error;
-                args.arg1 = message;
+                args.argi2 = modality;
+                args.argi3 = error;
+                args.argi4 = vendorCode;
                 mHandler.obtainMessage(MSG_ON_ERROR, args).sendToTarget();
             }
         }
@@ -666,7 +671,8 @@
             final long ident = Binder.clearCallingIdentity();
             int error;
             try {
-                final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
+                final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId,
+                        opPackageName);
                 error = result.second;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -675,22 +681,30 @@
         }
 
         @Override
-        public boolean hasEnrolledBiometrics(int userId) {
+        public boolean hasEnrolledBiometrics(int userId, String opPackageName) {
             checkInternalPermission();
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                for (int i = 0; i < mAuthenticators.size(); i++) {
-                    if (mAuthenticators.get(i).mAuthenticator.hasEnrolledTemplates(userId)) {
+                for (AuthenticatorWrapper authenticator : mAuthenticators) {
+                    if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) {
                         return true;
                     }
                 }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception", e);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
             return false;
         }
 
+        @Override
+        public void registerAuthenticator(int id, int strength, int modality,
+                IBiometricAuthenticator authenticator) {
+            mAuthenticators.add(new AuthenticatorWrapper(id, strength, modality, authenticator));
+        }
+
         @Override // Binder call
         public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)
                 throws RemoteException {
@@ -710,9 +724,11 @@
             checkInternalPermission();
             final long ident = Binder.clearCallingIdentity();
             try {
-                for (int i = 0; i < mAuthenticators.size(); i++) {
-                    mAuthenticators.get(i).getAuthenticator().setActiveUser(userId);
+                for (AuthenticatorWrapper authenticator : mAuthenticators) {
+                    authenticator.impl.setActiveUser(userId);
                 }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception", e);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -723,11 +739,8 @@
             checkInternalPermission();
             final long ident = Binder.clearCallingIdentity();
             try {
-                if (mFingerprintService != null) {
-                    mFingerprintService.resetTimeout(token);
-                }
-                if (mFaceService != null) {
-                    mFaceService.resetLockout(token);
+                for (AuthenticatorWrapper authenticator : mAuthenticators) {
+                    authenticator.impl.resetLockout(token);
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote exception", e);
@@ -750,40 +763,69 @@
         }
     }
 
+    /**
+     * Class for injecting dependencies into BiometricService.
+     * TODO(b/141025588): Replace with a dependency injection framework (e.g. Guice, Dagger).
+     */
     @VisibleForTesting
-    static class Injector {
-        IActivityManager getActivityManagerService() {
+    public static class Injector {
+
+        @VisibleForTesting
+        public IActivityManager getActivityManagerService() {
             return ActivityManager.getService();
         }
 
-        IStatusBarService getStatusBarService() {
+        @VisibleForTesting
+        public IStatusBarService getStatusBarService() {
             return IStatusBarService.Stub.asInterface(
                     ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         }
 
-        IFingerprintService getFingerprintService() {
-            return IFingerprintService.Stub.asInterface(
-                    ServiceManager.getService(Context.FINGERPRINT_SERVICE));
+        /**
+         * Allows to mock FaceAuthenticator for testing.
+         */
+        @VisibleForTesting
+        public IBiometricAuthenticator getFingerprintAuthenticator() {
+            return new FingerprintAuthenticator(IFingerprintService.Stub.asInterface(
+                    ServiceManager.getService(Context.FINGERPRINT_SERVICE)));
         }
 
-        IFaceService getFaceService() {
-            return IFaceService.Stub.asInterface(ServiceManager.getService(Context.FACE_SERVICE));
+        /**
+         * Allows to mock FaceAuthenticator for testing.
+         */
+        @VisibleForTesting
+        public IBiometricAuthenticator getFaceAuthenticator() {
+            return new FaceAuthenticator(
+                    IFaceService.Stub.asInterface(ServiceManager.getService(Context.FACE_SERVICE)));
         }
 
-        SettingObserver getSettingObserver(Context context, Handler handler,
+        /**
+         * Allows to mock SettingObserver for testing.
+         */
+        @VisibleForTesting
+        public SettingObserver getSettingObserver(Context context, Handler handler,
                 List<EnabledOnKeyguardCallback> callbacks) {
             return new SettingObserver(context, handler, callbacks);
         }
 
-        KeyStore getKeyStore() {
+        @VisibleForTesting
+        public KeyStore getKeyStore() {
             return KeyStore.getInstance();
         }
 
-        boolean isDebugEnabled(Context context, int userId) {
+        /**
+         * Allows to enable/disable debug logs.
+         */
+        @VisibleForTesting
+        public boolean isDebugEnabled(Context context, int userId) {
             return Utils.isDebugEnabled(context, userId);
         }
 
-        void publishBinderService(BiometricService service, IBiometricService.Stub impl) {
+        /**
+         * Allows to stub publishBinderService(...) for testing.
+         */
+        @VisibleForTesting
+        public void publishBinderService(BiometricService service, IBiometricService.Stub impl) {
             service.publishBinderService(Context.BIOMETRIC_SERVICE, impl);
         }
     }
@@ -812,9 +854,9 @@
                 mEnabledOnKeyguardCallbacks);
 
         final PackageManager pm = context.getPackageManager();
+        mHasFeatureFace = pm.hasSystemFeature(PackageManager.FEATURE_FACE);
         mHasFeatureFingerprint = pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
         mHasFeatureIris = pm.hasSystemFeature(PackageManager.FEATURE_IRIS);
-        mHasFeatureFace = pm.hasSystemFeature(PackageManager.FEATURE_FACE);
 
         try {
             injector.getActivityManagerService().registerUserSwitchObserver(
@@ -833,26 +875,30 @@
 
     @Override
     public void onStart() {
-        // TODO: maybe get these on-demand
-        if (mHasFeatureFingerprint) {
-            mFingerprintService = mInjector.getFingerprintService();
-        }
-        if (mHasFeatureFace) {
-            mFaceService = mInjector.getFaceService();
+        // TODO(b/141025588): remove this code block once AuthService is integrated.
+        {
+            if (mHasFeatureFace) {
+                try {
+                    mImpl.registerAuthenticator(0, 0, TYPE_FACE, mInjector.getFaceAuthenticator());
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Remote exception", e);
+                }
+            }
+            if (mHasFeatureFingerprint) {
+                try {
+                    mImpl.registerAuthenticator(0, 0, TYPE_FINGERPRINT,
+                            mInjector.getFingerprintAuthenticator());
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Remote exception", e);
+                }
+            }
+            if (mHasFeatureIris) {
+                Slog.e(TAG, "Iris is not supported");
+            }
         }
 
         mKeyStore = mInjector.getKeyStore();
         mStatusBarService = mInjector.getStatusBarService();
-
-        // Cache the authenticators
-        for (int featureId : FEATURE_ID) {
-            if (hasFeature(featureId)) {
-                AuthenticatorWrapper authenticator =
-                        new AuthenticatorWrapper(featureId, getAuthenticator(featureId));
-                mAuthenticators.add(authenticator);
-            }
-        }
-
         mInjector.publishBinderService(this, mImpl);
     }
 
@@ -868,7 +914,7 @@
      * {@link BiometricAuthenticator#TYPE_FACE}
      * and the error containing one of the {@link BiometricConstants} errors.
      */
-    private Pair<Integer, Integer> checkAndGetBiometricModality(int userId) {
+    private Pair<Integer, Integer> checkAndGetBiometricModality(int userId, String opPackageName) {
         // No biometric features, send error
         if (mAuthenticators.isEmpty()) {
             return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT);
@@ -886,23 +932,26 @@
 
         int modality = TYPE_NONE;
         int firstHwAvailable = TYPE_NONE;
-        for (AuthenticatorWrapper authenticatorWrapper : mAuthenticators) {
-            modality = authenticatorWrapper.getType();
-            BiometricAuthenticator authenticator = authenticatorWrapper.getAuthenticator();
-            if (authenticator.isHardwareDetected()) {
-                isHardwareDetected = true;
-                if (firstHwAvailable == TYPE_NONE) {
-                    // Store the first one since we want to return the error in correct priority
-                    // order.
-                    firstHwAvailable = modality;
-                }
-                if (authenticator.hasEnrolledTemplates(userId)) {
-                    hasTemplatesEnrolled = true;
-                    if (isEnabledForApp(modality, userId)) {
-                        enabledForApps = true;
-                        break;
+        for (AuthenticatorWrapper authenticator : mAuthenticators) {
+            modality = authenticator.modality;
+            try {
+                if (authenticator.impl.isHardwareDetected(opPackageName)) {
+                    isHardwareDetected = true;
+                    if (firstHwAvailable == TYPE_NONE) {
+                        // Store the first one since we want to return the error in correct priority
+                        // order.
+                        firstHwAvailable = modality;
+                    }
+                    if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) {
+                        hasTemplatesEnrolled = true;
+                        if (isEnabledForApp(modality, userId)) {
+                            enabledForApps = true;
+                            break;
+                        }
                     }
                 }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote exception", e);
             }
         }
 
@@ -926,7 +975,7 @@
     }
 
     private boolean isEnabledForApp(int modality, int userId) {
-        switch(modality) {
+        switch (modality) {
             case TYPE_FINGERPRINT:
                 return true;
             case TYPE_IRIS:
@@ -939,49 +988,6 @@
         }
     }
 
-    private String getErrorString(int type, int error, int vendorCode) {
-        switch (type) {
-            case TYPE_FINGERPRINT:
-                return FingerprintManager.getErrorString(getContext(), error, vendorCode);
-            case TYPE_IRIS:
-                Slog.w(TAG, "Modality not supported");
-                return null; // not supported
-            case TYPE_FACE:
-                return FaceManager.getErrorString(getContext(), error, vendorCode);
-            default:
-                Slog.w(TAG, "Unable to get error string for modality: " + type);
-                return null;
-        }
-    }
-
-    private BiometricAuthenticator getAuthenticator(int type) {
-        switch (type) {
-            case TYPE_FINGERPRINT:
-                return (FingerprintManager)
-                        getContext().getSystemService(Context.FINGERPRINT_SERVICE);
-            case TYPE_IRIS:
-                return null;
-            case TYPE_FACE:
-                return (FaceManager)
-                        getContext().getSystemService(Context.FACE_SERVICE);
-            default:
-                return null;
-        }
-    }
-
-    private boolean hasFeature(int type) {
-        switch (type) {
-            case TYPE_FINGERPRINT:
-                return mHasFeatureFingerprint;
-            case TYPE_IRIS:
-                return mHasFeatureIris;
-            case TYPE_FACE:
-                return mHasFeatureFace;
-            default:
-                return false;
-        }
-    }
-
     private void logDialogDismissed(int reason) {
         if (reason == BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED) {
             // Explicit auth, authentication confirmed.
@@ -1081,14 +1087,14 @@
 
             // Notify SysUI that the biometric has been authenticated. SysUI already knows
             // the implicit/explicit state and will react accordingly.
-            mStatusBarService.onBiometricAuthenticated(true, null /* failureReason */);
+            mStatusBarService.onBiometricAuthenticated();
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception", e);
         }
     }
 
-    private void handleAuthenticationRejected(String failureReason) {
-        Slog.v(TAG, "handleAuthenticationRejected: " + failureReason);
+    private void handleAuthenticationRejected() {
+        Slog.v(TAG, "handleAuthenticationRejected()");
         try {
             // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
             // after user dismissed/canceled dialog).
@@ -1097,7 +1103,8 @@
                 return;
             }
 
-            mStatusBarService.onBiometricAuthenticated(false, failureReason);
+            mStatusBarService.onBiometricError(TYPE_NONE,
+                    BiometricConstants.BIOMETRIC_PAUSED_REJECTED, 0 /* vendorCode */);
 
             // TODO: This logic will need to be updated if BP is multi-modal
             if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) {
@@ -1112,8 +1119,9 @@
         }
     }
 
-    private void handleAuthenticationTimedOut(String message) {
-        Slog.v(TAG, "handleAuthenticationTimedOut: " + message);
+    private void handleAuthenticationTimedOut(int modality, int error, int vendorCode) {
+        Slog.v(TAG, String.format("handleAuthenticationTimedOut(%d, %d, %d)", modality, error,
+                vendorCode));
         try {
             // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
             // after user dismissed/canceled dialog).
@@ -1122,14 +1130,14 @@
                 return;
             }
 
-            mStatusBarService.onBiometricAuthenticated(false, message);
+            mStatusBarService.onBiometricError(modality, error, vendorCode);
             mCurrentAuthSession.mState = STATE_AUTH_PAUSED;
         } catch (RemoteException e) {
             Slog.e(TAG, "Remote exception", e);
         }
     }
 
-    private void handleOnError(int cookie, int error, String message) {
+    private void handleOnError(int cookie, int modality, int error, int vendorCode) {
         Slog.d(TAG, "handleOnError: " + error + " cookie: " + cookie);
         // Errors can either be from the current auth session or the pending auth session.
         // The pending auth session may receive errors such as ERROR_LOCKOUT before
@@ -1140,7 +1148,7 @@
         try {
             if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
                 mCurrentAuthSession.mErrorEscrow = error;
-                mCurrentAuthSession.mErrorStringEscrow = message;
+                mCurrentAuthSession.mVendorCodeEscrow = vendorCode;
 
                 if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
                     final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
@@ -1148,20 +1156,20 @@
                     if (mCurrentAuthSession.isAllowDeviceCredential() && errorLockout) {
                         // SystemUI handles transition from biometric to device credential.
                         mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
-                        mStatusBarService.onBiometricError(error, message);
+                        mStatusBarService.onBiometricError(modality, error, vendorCode);
                     } else {
                         mCurrentAuthSession.mState = STATE_ERROR_PENDING_SYSUI;
                         if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
                             mStatusBarService.hideAuthenticationDialog();
                         } else {
-                            mStatusBarService.onBiometricError(error, message);
+                            mStatusBarService.onBiometricError(modality, error, vendorCode);
                         }
                     }
                 } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) {
                     // In the "try again" state, we should forward canceled errors to
                     // the client and and clean up. The only error we should get here is
                     // ERROR_CANCELED due to another client kicking us out.
-                    mCurrentAuthSession.mClientReceiver.onError(error, message);
+                    mCurrentAuthSession.mClientReceiver.onError(modality, error, vendorCode);
                     mStatusBarService.hideAuthenticationDialog();
                     mCurrentAuthSession = null;
                 } else if (mCurrentAuthSession.mState == STATE_SHOWING_DEVICE_CREDENTIAL) {
@@ -1197,7 +1205,7 @@
                                 mCurrentAuthSession.mUserId,
                                 mCurrentAuthSession.mOpPackageName);
                     } else {
-                        mPendingAuthSession.mClientReceiver.onError(error, message);
+                        mPendingAuthSession.mClientReceiver.onError(modality, error, vendorCode);
                         mPendingAuthSession = null;
                     }
                 } else {
@@ -1261,8 +1269,10 @@
 
                 case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
                     mCurrentAuthSession.mClientReceiver.onError(
+                            mCurrentAuthSession.mModality,
                             BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
-                            getContext().getString(R.string.biometric_error_user_canceled));
+                            0 /* vendorCode */
+                    );
                     // Cancel authentication. Skip the token/package check since we are cancelling
                     // from system server. The interface is permission protected so this is fine.
                     cancelInternal(null /* token */, null /* package */, false /* fromClient */);
@@ -1270,8 +1280,11 @@
 
                 case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED:
                 case BiometricPrompt.DISMISSED_REASON_ERROR:
-                    mCurrentAuthSession.mClientReceiver.onError(mCurrentAuthSession.mErrorEscrow,
-                            mCurrentAuthSession.mErrorStringEscrow);
+                    mCurrentAuthSession.mClientReceiver.onError(
+                            mCurrentAuthSession.mModality,
+                            mCurrentAuthSession.mErrorEscrow,
+                            mCurrentAuthSession.mVendorCodeEscrow
+                    );
                     break;
 
                 default:
@@ -1354,30 +1367,35 @@
             mPendingAuthSession = null;
 
             mCurrentAuthSession.mState = STATE_AUTH_STARTED;
-            try {
-                int modality = TYPE_NONE;
-                it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator();
-                while (it.hasNext()) {
-                    Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
-                    if (pair.getKey() == TYPE_FINGERPRINT) {
-                        mFingerprintService.startPreparedClient(pair.getValue());
-                    } else if (pair.getKey() == TYPE_IRIS) {
-                        Slog.e(TAG, "Iris unsupported");
-                    } else if (pair.getKey() == TYPE_FACE) {
-                        mFaceService.startPreparedClient(pair.getValue());
-                    } else {
-                        Slog.e(TAG, "Unknown modality: " + pair.getKey());
+            int modality = TYPE_NONE;
+            it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
+                boolean foundAuthenticator = false;
+                for (AuthenticatorWrapper authenticator : mAuthenticators) {
+                    if (authenticator.modality == pair.getKey()) {
+                        foundAuthenticator = true;
+                        try {
+                            authenticator.impl.startPreparedClient(pair.getValue());
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "Remote exception", e);
+                        }
                     }
-                    modality |= pair.getKey();
                 }
+                if (!foundAuthenticator) {
+                    Slog.e(TAG, "Unknown modality: " + pair.getKey());
+                }
+                modality |= pair.getKey();
+            }
 
-                if (!continuing) {
+            if (!continuing) {
+                try {
                     mStatusBarService.showAuthenticationDialog(mCurrentAuthSession.mBundle,
                             mInternalReceiver, modality, requireConfirmation, userId,
                             mCurrentAuthSession.mOpPackageName);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Remote exception", e);
                 }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote exception", e);
             }
         }
     }
@@ -1387,7 +1405,8 @@
             int callingUid, int callingPid, int callingUserId) {
 
         mHandler.post(() -> {
-            final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
+            final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId,
+                    opPackageName);
             final int modality = result.first;
             final int error = result.second;
 
@@ -1400,23 +1419,7 @@
             } else if (error != BiometricConstants.BIOMETRIC_SUCCESS) {
                 // Check for errors, notify callback, and return
                 try {
-                    final String hardwareUnavailable =
-                            getContext().getString(R.string.biometric_error_hw_unavailable);
-                    switch (error) {
-                        case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT:
-                            receiver.onError(error, hardwareUnavailable);
-                            break;
-                        case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE:
-                            receiver.onError(error, hardwareUnavailable);
-                            break;
-                        case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS:
-                            receiver.onError(error,
-                                    getErrorString(modality, error, 0 /* vendorCode */));
-                            break;
-                        default:
-                            Slog.e(TAG, "Unhandled error");
-                            break;
-                    }
+                    receiver.onError(modality, error, 0 /* vendorCode */);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Unable to send error", e);
                 }
@@ -1435,41 +1438,41 @@
      * modality/modalities to start authenticating with. authenticateInternal() should only be
      * used for:
      * 1) Preparing <Biometric>Services for authentication when BiometricPrompt#authenticate is,
-     *    invoked, shortly after which BiometricPrompt is shown and authentication starts
+     * invoked, shortly after which BiometricPrompt is shown and authentication starts
      * 2) Preparing <Biometric>Services for authentication when BiometricPrompt is already shown
-     *    and the user has pressed "try again"
+     * and the user has pressed "try again"
      */
     private void authenticateInternal(IBinder token, long sessionId, int userId,
             IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
             int callingUid, int callingPid, int callingUserId, int modality) {
+        boolean requireConfirmation = bundle.getBoolean(
+                BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
+        if ((modality & TYPE_FACE) != 0) {
+            // Check if the user has forced confirmation to be required in Settings.
+            requireConfirmation = requireConfirmation
+                    || mSettingObserver.getFaceAlwaysRequireConfirmation(userId);
+        }
+        // Generate random cookies to pass to the services that should prepare to start
+        // authenticating. Store the cookie here and wait for all services to "ack"
+        // with the cookie. Once all cookies are received, we can show the prompt
+        // and let the services start authenticating. The cookie should be non-zero.
+        final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
+        final int authenticators = bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED);
+        Slog.d(TAG, "Creating auth session. Modality: " + modality
+                + ", cookie: " + cookie
+                + ", authenticators: " + authenticators);
+        final HashMap<Integer, Integer> modalities = new HashMap<>();
+
+        // If it's only device credential, we don't need to wait - LockSettingsService is
+        // always ready to check credential (SystemUI invokes that path).
+        if ((authenticators & ~Authenticator.TYPE_CREDENTIAL) != 0) {
+            modalities.put(modality, cookie);
+        }
+        mPendingAuthSession = new AuthSession(modalities, token, sessionId, userId,
+                receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
+                modality, requireConfirmation);
+
         try {
-            boolean requireConfirmation = bundle.getBoolean(
-                    BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
-            if ((modality & TYPE_FACE) != 0) {
-                // Check if the user has forced confirmation to be required in Settings.
-                requireConfirmation = requireConfirmation
-                        || mSettingObserver.getFaceAlwaysRequireConfirmation(userId);
-            }
-            // Generate random cookies to pass to the services that should prepare to start
-            // authenticating. Store the cookie here and wait for all services to "ack"
-            // with the cookie. Once all cookies are received, we can show the prompt
-            // and let the services start authenticating. The cookie should be non-zero.
-            final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
-            final int authenticators = bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED);
-            Slog.d(TAG, "Creating auth session. Modality: " + modality
-                    + ", cookie: " + cookie
-                    + ", authenticators: " + authenticators);
-            final HashMap<Integer, Integer> modalities = new HashMap<>();
-
-            // If it's only device credential, we don't need to wait - LockSettingsService is
-            // always ready to check credential (SystemUI invokes that path).
-            if ((authenticators & ~Authenticator.TYPE_CREDENTIAL) != 0) {
-                modalities.put(modality, cookie);
-            }
-            mPendingAuthSession = new AuthSession(modalities, token, sessionId, userId,
-                    receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
-                    modality, requireConfirmation);
-
             if (authenticators == Authenticator.TYPE_CREDENTIAL) {
                 mPendingAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
                 mCurrentAuthSession = mPendingAuthSession;
@@ -1484,19 +1487,10 @@
                         mCurrentAuthSession.mOpPackageName);
             } else {
                 mPendingAuthSession.mState = STATE_AUTH_CALLED;
-                // No polymorphism :(
-                if ((modality & TYPE_FINGERPRINT) != 0) {
-                    mFingerprintService.prepareForAuthentication(token, sessionId, userId,
-                            mInternalReceiver, opPackageName, cookie,
-                            callingUid, callingPid, callingUserId);
-                }
-                if ((modality & TYPE_IRIS) != 0) {
-                    Slog.w(TAG, "Iris unsupported");
-                }
-                if ((modality & TYPE_FACE) != 0) {
-                    mFaceService.prepareForAuthentication(requireConfirmation,
-                            token, sessionId, userId, mInternalReceiver, opPackageName,
-                            cookie, callingUid, callingPid, callingUserId);
+                for (AuthenticatorWrapper authenticator : mAuthenticators) {
+                    authenticator.impl.prepareForAuthentication(requireConfirmation, token,
+                            sessionId, userId, mInternalReceiver, opPackageName, cookie, callingUid,
+                            callingPid, callingUserId);
                 }
             }
         } catch (RemoteException e) {
@@ -1517,11 +1511,10 @@
             try {
                 // Send error to client
                 mCurrentAuthSession.mClientReceiver.onError(
+                        mCurrentAuthSession.mModality,
                         BiometricConstants.BIOMETRIC_ERROR_CANCELED,
-                        getContext().getString(
-                                com.android.internal.R.string.biometric_error_user_canceled)
+                        0 /* vendorCode */
                 );
-
                 mCurrentAuthSession = null;
                 mStatusBarService.hideAuthenticationDialog();
             } catch (RemoteException e) {
@@ -1537,30 +1530,25 @@
         final int callingPid = Binder.getCallingPid();
         final int callingUserId = UserHandle.getCallingUserId();
 
-        try {
-            if (mCurrentAuthSession == null) {
-                Slog.w(TAG, "Skipping cancelInternal");
-                return;
-            } else if (mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
-                Slog.w(TAG, "Skipping cancelInternal, state: " + mCurrentAuthSession.mState);
-                return;
-            }
+        if (mCurrentAuthSession == null) {
+            Slog.w(TAG, "Skipping cancelInternal");
+            return;
+        } else if (mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
+            Slog.w(TAG, "Skipping cancelInternal, state: " + mCurrentAuthSession.mState);
+            return;
+        }
 
-            // TODO: For multiple modalities, send a single ERROR_CANCELED only when all
-            // drivers have canceled authentication.
-            if ((mCurrentAuthSession.mModality & TYPE_FINGERPRINT) != 0) {
-                mFingerprintService.cancelAuthenticationFromService(token, opPackageName,
-                        callingUid, callingPid, callingUserId, fromClient);
+        // TODO: For multiple modalities, send a single ERROR_CANCELED only when all
+        // drivers have canceled authentication.
+        for (AuthenticatorWrapper authenticator : mAuthenticators) {
+            if ((authenticator.modality & mCurrentAuthSession.mModality) != 0) {
+                try {
+                    authenticator.impl.cancelAuthenticationFromService(token, opPackageName,
+                            callingUid, callingPid, callingUserId, fromClient);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Unable to cancel authentication");
+                }
             }
-            if ((mCurrentAuthSession.mModality & TYPE_IRIS) != 0) {
-                Slog.w(TAG, "Iris unsupported");
-            }
-            if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) {
-                mFaceService.cancelAuthenticationFromService(token, opPackageName,
-                        callingUid, callingPid, callingUserId, fromClient);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Unable to cancel authentication");
         }
     }
 }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/face/FaceAuthenticator.java
new file mode 100644
index 0000000..5df5b29d
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/face/FaceAuthenticator.java
@@ -0,0 +1,75 @@
+/*
+ * 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.biometrics.face;
+
+import android.hardware.biometrics.IBiometricAuthenticator;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
+import android.hardware.face.IFaceService;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+/**
+ * TODO(b/141025588): Add JavaDoc.
+ */
+public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
+    private final IFaceService mFaceService;
+
+    public FaceAuthenticator(IFaceService faceService) {
+        mFaceService = faceService;
+    }
+
+    @Override
+    public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
+            long sessionId, int userId, IBiometricServiceReceiverInternal wrapperReceiver,
+            String opPackageName, int cookie, int callingUid, int callingPid, int callingUserId)
+            throws RemoteException {
+        mFaceService.prepareForAuthentication(requireConfirmation, token, sessionId, userId,
+                wrapperReceiver, opPackageName, cookie, callingUid, callingPid, callingUserId);
+    }
+
+    @Override
+    public void startPreparedClient(int cookie) throws RemoteException {
+        mFaceService.startPreparedClient(cookie);
+    }
+
+    @Override
+    public void cancelAuthenticationFromService(IBinder token, String opPackageName, int callingUid,
+            int callingPid, int callingUserId, boolean fromClient) throws RemoteException {
+        mFaceService.cancelAuthenticationFromService(token, opPackageName, callingUid, callingPid,
+                callingUserId, fromClient);
+    }
+
+    @Override
+    public boolean isHardwareDetected(String opPackageName) throws RemoteException {
+        return mFaceService.isHardwareDetected(opPackageName);
+    }
+
+    @Override
+    public boolean hasEnrolledTemplates(int userId, String opPackageName) throws RemoteException {
+        return mFaceService.hasEnrolledFaces(userId, opPackageName);
+    }
+
+    @Override
+    public void resetLockout(byte[] token) throws RemoteException {
+        mFaceService.resetLockout(token);
+    }
+
+    @Override
+    public void setActiveUser(int uid) throws RemoteException {
+        mFaceService.setActiveUser(uid);
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 1b13212..a0c8e23 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.MANAGE_BIOMETRIC;
 import static android.Manifest.permission.RESET_FACE_LOCKOUT;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
 
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
@@ -538,7 +539,7 @@
 
         // TODO: refactor out common code here
         @Override // Binder call
-        public boolean isHardwareDetected(long deviceId, String opPackageName) {
+        public boolean isHardwareDetected(String opPackageName) {
             checkPermission(USE_BIOMETRIC_INTERNAL);
             if (!canUseBiometric(opPackageName, false /* foregroundOnly */,
                     Binder.getCallingUid(), Binder.getCallingPid(),
@@ -752,8 +753,7 @@
         public void onError(long deviceId, int error, int vendorCode, int cookie)
                 throws RemoteException {
             if (getWrapperReceiver() != null) {
-                getWrapperReceiver().onError(cookie, error,
-                        FaceManager.getErrorString(getContext(), error, vendorCode));
+                getWrapperReceiver().onError(cookie, TYPE_FACE, error, vendorCode);
             }
         }
     }
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintAuthenticator.java
new file mode 100644
index 0000000..6150de1
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintAuthenticator.java
@@ -0,0 +1,75 @@
+/*
+ * 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.biometrics.fingerprint;
+
+import android.hardware.biometrics.IBiometricAuthenticator;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
+import android.hardware.fingerprint.IFingerprintService;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+/**
+ * TODO(b/141025588): Add JavaDoc.
+ */
+public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub {
+    private final IFingerprintService mFingerprintService;
+
+    public FingerprintAuthenticator(IFingerprintService fingerprintService) {
+        mFingerprintService = fingerprintService;
+    }
+
+    @Override
+    public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
+            long sessionId, int userId, IBiometricServiceReceiverInternal wrapperReceiver,
+            String opPackageName, int cookie, int callingUid, int callingPid, int callingUserId)
+            throws RemoteException {
+        mFingerprintService.prepareForAuthentication(token, sessionId, userId, wrapperReceiver,
+                opPackageName, cookie, callingUid, callingPid, callingUserId);
+    }
+
+    @Override
+    public void startPreparedClient(int cookie) throws RemoteException {
+        mFingerprintService.startPreparedClient(cookie);
+    }
+
+    @Override
+    public void cancelAuthenticationFromService(IBinder token, String opPackageName, int callingUid,
+            int callingPid, int callingUserId, boolean fromClient) throws RemoteException {
+        mFingerprintService.cancelAuthenticationFromService(token, opPackageName, callingUid,
+                callingPid, callingUserId, fromClient);
+    }
+
+    @Override
+    public boolean isHardwareDetected(String opPackageName) throws RemoteException {
+        return mFingerprintService.isHardwareDetected(opPackageName);
+    }
+
+    @Override
+    public boolean hasEnrolledTemplates(int userId, String opPackageName) throws RemoteException {
+        return mFingerprintService.hasEnrolledFingerprints(userId, opPackageName);
+    }
+
+    @Override
+    public void resetLockout(byte[] token) throws RemoteException {
+        mFingerprintService.resetTimeout(token);
+    }
+
+    @Override
+    public void setActiveUser(int uid) throws RemoteException {
+        mFingerprintService.setActiveUser(uid);
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index d85af2e..44797ad 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -22,6 +22,7 @@
 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
 import static android.Manifest.permission.USE_BIOMETRIC;
 import static android.Manifest.permission.USE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 
 import android.app.ActivityManager;
 import android.app.AlarmManager;
@@ -350,7 +351,7 @@
 
         // TODO: refactor out common code here
         @Override // Binder call
-        public boolean isHardwareDetected(long deviceId, String opPackageName) {
+        public boolean isHardwareDetected(String opPackageName) {
             if (!canUseBiometric(opPackageName, false /* foregroundOnly */,
                     Binder.getCallingUid(), Binder.getCallingPid(),
                     UserHandle.getCallingUserId())) {
@@ -480,8 +481,7 @@
         public void onError(long deviceId, int error, int vendorCode, int cookie)
                 throws RemoteException {
             if (getWrapperReceiver() != null) {
-                getWrapperReceiver().onError(cookie, error,
-                        FingerprintManager.getErrorString(getContext(), error, vendorCode));
+                getWrapperReceiver().onError(cookie, TYPE_FINGERPRINT, error, vendorCode);
             }
         }
     }
diff --git a/services/core/java/com/android/server/biometrics/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/iris/IrisAuthenticator.java
new file mode 100644
index 0000000..c44b8e7
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/iris/IrisAuthenticator.java
@@ -0,0 +1,68 @@
+/*
+ * 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.biometrics.iris;
+
+import android.hardware.biometrics.IBiometricAuthenticator;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
+import android.hardware.iris.IIrisService;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+/**
+ * TODO(b/141025588): Add JavaDoc.
+ */
+public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
+    private final IIrisService mIrisService;
+
+    public IrisAuthenticator(IIrisService irisService) {
+        mIrisService = irisService;
+    }
+
+    @Override
+    public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
+            long sessionId, int userId, IBiometricServiceReceiverInternal wrapperReceiver,
+            String opPackageName, int cookie, int callingUid, int callingPid, int callingUserId)
+            throws RemoteException {
+    }
+
+    @Override
+    public void startPreparedClient(int cookie) throws RemoteException {
+    }
+
+    @Override
+    public void cancelAuthenticationFromService(IBinder token, String opPackageName, int callingUid,
+            int callingPid, int callingUserId, boolean fromClient) throws RemoteException {
+    }
+
+    @Override
+    public boolean isHardwareDetected(String opPackageName) throws RemoteException {
+        return false;
+    }
+
+    @Override
+    public boolean hasEnrolledTemplates(int userId, String opPackageName) throws RemoteException {
+        return false;
+    }
+
+    @Override
+    public void resetLockout(byte[] token) throws RemoteException {
+    }
+
+    @Override
+    public void setActiveUser(int uid) throws RemoteException {
+    }
+}
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 8a7dcc1..9ac9955 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.util.StatsLog;
 
@@ -53,8 +54,8 @@
     }
 
     @Override
-    public void reportChangeByPackageName(long changeId, String packageName) {
-        ApplicationInfo appInfo = getApplicationInfo(packageName);
+    public void reportChangeByPackageName(long changeId, String packageName, int userId) {
+        ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return;
         }
@@ -79,8 +80,8 @@
     }
 
     @Override
-    public boolean isChangeEnabledByPackageName(long changeId, String packageName) {
-        ApplicationInfo appInfo = getApplicationInfo(packageName);
+    public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
+        ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return true;
         }
@@ -95,7 +96,8 @@
         }
         boolean enabled = true;
         for (String packageName : packages) {
-            enabled = enabled && isChangeEnabledByPackageName(changeId, packageName);
+            enabled = enabled && isChangeEnabledByPackageName(changeId, packageName,
+                    UserHandle.getUserId(uid));
         }
         return enabled;
     }
@@ -126,9 +128,9 @@
         mChangeReporter.resetReportedChanges(appInfo.uid);
     }
 
-    private ApplicationInfo getApplicationInfo(String packageName) {
+    private ApplicationInfo getApplicationInfo(String packageName, int userId) {
         try {
-            return mContext.getPackageManager().getApplicationInfo(packageName, 0);
+            return mContext.getPackageManager().getApplicationInfoAsUser(packageName, 0, userId);
         } catch (PackageManager.NameNotFoundException e) {
             Slog.e(TAG, "No installed package " + packageName);
         }
diff --git a/services/core/java/com/android/server/compat/PlatformCompatNative.java b/services/core/java/com/android/server/compat/PlatformCompatNative.java
new file mode 100644
index 0000000..85dfbf4
--- /dev/null
+++ b/services/core/java/com/android/server/compat/PlatformCompatNative.java
@@ -0,0 +1,50 @@
+/*
+ * 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.compat;
+
+import com.android.internal.compat.IPlatformCompatNative;
+
+/**
+ * @hide
+ */
+public class PlatformCompatNative extends IPlatformCompatNative.Stub {
+    private final PlatformCompat mPlatformCompat;
+
+    public PlatformCompatNative(PlatformCompat platformCompat) {
+        mPlatformCompat = platformCompat;
+    }
+
+    @Override
+    public void reportChangeByPackageName(long changeId, String packageName, int userId) {
+        mPlatformCompat.reportChangeByPackageName(changeId, packageName, userId);
+    }
+
+    @Override
+    public void reportChangeByUid(long changeId, int uid) {
+        mPlatformCompat.reportChangeByUid(changeId, uid);
+    }
+
+    @Override
+    public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
+        return mPlatformCompat.isChangeEnabledByPackageName(changeId, packageName, userId);
+    }
+
+    @Override
+    public boolean isChangeEnabledByUid(long changeId, int uid) {
+        return mPlatformCompat.isChangeEnabledByUid(changeId, uid);
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 077c405..d13e675 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -53,7 +53,8 @@
         NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET),
         LOGGED_IN(SystemMessage.NOTE_NETWORK_LOGGED_IN),
         PARTIAL_CONNECTIVITY(SystemMessage.NOTE_NETWORK_PARTIAL_CONNECTIVITY),
-        SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN);
+        SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN),
+        PRIVATE_DNS_BROKEN(SystemMessage.NOTE_NETWORK_PRIVATE_DNS_BROKEN);
 
         public final int eventId;
 
@@ -175,13 +176,23 @@
         }
 
         Resources r = Resources.getSystem();
-        CharSequence title;
-        CharSequence details;
+        final CharSequence title;
+        final CharSequence details;
         int icon = getIcon(transportType, notifyType);
         if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
             title = r.getString(R.string.wifi_no_internet,
                     WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
             details = r.getString(R.string.wifi_no_internet_detailed);
+        } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) {
+            if (transportType == TRANSPORT_CELLULAR) {
+                title = r.getString(R.string.mobile_no_internet);
+            } else if (transportType == TRANSPORT_WIFI) {
+                title = r.getString(R.string.wifi_no_internet,
+                        WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
+            } else {
+                title = r.getString(R.string.other_networks_no_internet);
+            }
+            details = r.getString(R.string.private_dns_broken_detailed);
         } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY
                 && transportType == TRANSPORT_WIFI) {
             title = r.getString(R.string.network_partial_connectivity,
@@ -357,8 +368,10 @@
         }
         switch (t) {
             case SIGN_IN:
-                return 5;
+                return 6;
             case PARTIAL_CONNECTIVITY:
+                return 5;
+            case PRIVATE_DNS_BROKEN:
                 return 4;
             case NO_INTERNET:
                 return 3;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 5fd5c4b..b3804c4 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -30,6 +30,7 @@
 import static android.net.ConnectivityManager.TETHERING_INVALID;
 import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
 import static android.net.ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
@@ -77,6 +78,9 @@
 import android.net.util.SharedLog;
 import android.net.util.VersionedBroadcastListener;
 import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pInfo;
+import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -290,6 +294,7 @@
         filter.addAction(CONNECTIVITY_ACTION);
         filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
         mContext.registerReceiver(mStateReceiver, filter, null, handler);
 
         filter = new IntentFilter();
@@ -354,6 +359,8 @@
 
         if (cfg.isWifi(iface)) {
             return TETHERING_WIFI;
+        } else if (cfg.isWifiP2p(iface)) {
+            return TETHERING_WIFI_P2P;
         } else if (cfg.isUsb(iface)) {
             return TETHERING_USB;
         } else if (cfg.isBluetooth(iface)) {
@@ -527,6 +534,7 @@
 
     public void untetherAll() {
         stopTethering(TETHERING_WIFI);
+        stopTethering(TETHERING_WIFI_P2P);
         stopTethering(TETHERING_USB);
         stopTethering(TETHERING_BLUETOOTH);
     }
@@ -713,6 +721,8 @@
                 handleConnectivityAction(intent);
             } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
                 handleWifiApAction(intent);
+            } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
+                handleWifiP2pAction(intent);
             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
                 mLog.log("OBSERVED configuration changed");
                 updateConfiguration();
@@ -789,6 +799,39 @@
                 }
             }
         }
+
+        private void handleWifiP2pAction(Intent intent) {
+            if (mConfig.isWifiP2pLegacyTetheringMode()) return;
+
+            final WifiP2pInfo p2pInfo =
+                    (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
+            final WifiP2pGroup group =
+                    (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
+
+            if (VDBG) {
+                Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group);
+            }
+
+            if (p2pInfo == null) return;
+            // When a p2p group is disconnected, p2pInfo would be cleared.
+            // group is still valid for detecting whether this device is group owner.
+            if (group == null || !group.isGroupOwner()
+                    || TextUtils.isEmpty(group.getInterface())) return;
+
+            synchronized (Tethering.this.mPublicSync) {
+                // Enter below only if this device is Group Owner with a valid interface.
+                if (p2pInfo.groupFormed) {
+                    TetherState tetherState = mTetherStates.get(group.getInterface());
+                    if (tetherState == null
+                            || (tetherState.lastState != IpServer.STATE_TETHERED
+                                && tetherState.lastState != IpServer.STATE_LOCAL_ONLY)) {
+                        enableWifiIpServingLocked(group.getInterface(), IFACE_IP_MODE_LOCAL_ONLY);
+                    }
+                } else {
+                    disableWifiP2pIpServingLocked(group.getInterface());
+                }
+            }
+        }
     }
 
     @VisibleForTesting
@@ -823,14 +866,11 @@
         }
     }
 
-    private void disableWifiIpServingLocked(String ifname, int apState) {
-        mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
-
-        // Regardless of whether we requested this transition, the AP has gone
-        // down.  Don't try to tether again unless we're requested to do so.
-        // TODO: Remove this altogether, once Wi-Fi reliably gives us an
-        // interface name with every broadcast.
-        mWifiTetherRequested = false;
+    private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) {
+        mLog.log("Canceling WiFi tethering request -"
+                + " type=" + tetheringType
+                + " interface=" + ifname
+                + " state=" + apState);
 
         if (!TextUtils.isEmpty(ifname)) {
             final TetherState ts = mTetherStates.get(ifname);
@@ -842,7 +882,7 @@
 
         for (int i = 0; i < mTetherStates.size(); i++) {
             final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
-            if (ipServer.interfaceType() == TETHERING_WIFI) {
+            if (ipServer.interfaceType() == tetheringType) {
                 ipServer.unwanted();
                 return;
             }
@@ -853,6 +893,20 @@
                                            : "specified interface: " + ifname));
     }
 
+    private void disableWifiIpServingLocked(String ifname, int apState) {
+        // Regardless of whether we requested this transition, the AP has gone
+        // down.  Don't try to tether again unless we're requested to do so.
+        // TODO: Remove this altogether, once Wi-Fi reliably gives us an
+        // interface name with every broadcast.
+        mWifiTetherRequested = false;
+
+        disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState);
+    }
+
+    private void disableWifiP2pIpServingLocked(String ifname) {
+        disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* dummy */ 0);
+    }
+
     private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
         // Map wifiIpMode values to IpServer.Callback serving states, inferring
         // from mWifiTetherRequested as a final "best guess".
@@ -870,7 +924,7 @@
         }
 
         if (!TextUtils.isEmpty(ifname)) {
-            maybeTrackNewInterfaceLocked(ifname, TETHERING_WIFI);
+            maybeTrackNewInterfaceLocked(ifname);
             changeInterfaceState(ifname, ipServingMode);
         } else {
             mLog.e(String.format(
diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java
index 61e5d1f..75ba5b8 100644
--- a/services/core/java/com/android/server/location/CallerIdentity.java
+++ b/services/core/java/com/android/server/location/CallerIdentity.java
@@ -17,6 +17,7 @@
 package com.android.server.location;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 /**
  * Represents the calling process's uid, pid, and package name.
@@ -25,13 +26,15 @@
     public final int mUid;
     public final int mPid;
     public final String mPackageName;
+    public final @Nullable String mFeatureId;
     public final @NonNull String mListenerIdentifier;
 
-    public CallerIdentity(int uid, int pid, String packageName,
+    public CallerIdentity(int uid, int pid, String packageName, @Nullable String featureId,
             @NonNull String listenerIdentifier) {
         mUid = uid;
         mPid = pid;
         mPackageName = packageName;
+        mFeatureId = featureId;
         mListenerIdentifier = listenerIdentifier;
     }
 }
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 895c4b3..17a2169 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -17,6 +17,7 @@
 package com.android.server.location;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.ContentResolver;
@@ -152,7 +153,7 @@
     }
 
     public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
-            int allowedResolutionLevel, int uid, String packageName,
+            int allowedResolutionLevel, int uid, String packageName, @Nullable String featureId,
             @NonNull String listenerIdentifier) {
         if (D) {
             Slog.d(TAG, "addFence: request=" + request + ", geofence=" + geofence
@@ -160,8 +161,8 @@
         }
 
         GeofenceState state = new GeofenceState(geofence,
-                request.getExpireAt(), allowedResolutionLevel, uid, packageName, listenerIdentifier,
-                intent);
+                request.getExpireAt(), allowedResolutionLevel, uid, packageName, featureId,
+                listenerIdentifier, intent);
         synchronized (mLock) {
             // first make sure it doesn't already exist
             for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -304,7 +305,7 @@
                 int op = LocationManagerService.resolutionLevelToOp(state.mAllowedResolutionLevel);
                 if (op >= 0) {
                     if (mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, state.mUid,
-                            state.mPackageName, state.mListenerIdentifier)
+                            state.mPackageName, state.mFeatureId, state.mListenerIdentifier)
                             != AppOpsManager.MODE_ALLOWED) {
                         if (D) {
                             Slog.d(TAG, "skipping geofence processing for no op app: "
diff --git a/services/core/java/com/android/server/location/GeofenceState.java b/services/core/java/com/android/server/location/GeofenceState.java
index fe0719d..a91a1dc 100644
--- a/services/core/java/com/android/server/location/GeofenceState.java
+++ b/services/core/java/com/android/server/location/GeofenceState.java
@@ -18,6 +18,7 @@
 package com.android.server.location;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.location.Geofence;
 import android.location.Location;
@@ -39,6 +40,7 @@
     public final int mAllowedResolutionLevel;
     public final int mUid;
     public final String mPackageName;
+    public final @Nullable String mFeatureId;
     public final @NonNull String mListenerIdentifier;
     public final PendingIntent mIntent;
 
@@ -46,7 +48,8 @@
     double mDistanceToCenter;  // current distance to center of fence
 
     public GeofenceState(Geofence fence, long expireAt, int allowedResolutionLevel, int uid,
-            String packageName, @NonNull String listenerIdentifier, PendingIntent intent) {
+            String packageName, @Nullable String featureId, @NonNull String listenerIdentifier,
+            PendingIntent intent) {
         mState = STATE_UNKNOWN;
         mDistanceToCenter = Double.MAX_VALUE;
 
@@ -55,6 +58,7 @@
         mAllowedResolutionLevel = allowedResolutionLevel;
         mUid = uid;
         mPackageName = packageName;
+        mFeatureId = featureId;
         mListenerIdentifier = listenerIdentifier;
         mIntent = intent;
 
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index 0929d93..60ce1f4 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -182,7 +182,7 @@
         }
 
         return mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, callerIdentity.mUid,
-                callerIdentity.mPackageName,
+                callerIdentity.mPackageName, callerIdentity.mFeatureId,
                 "Location sent to " + callerIdentity.mListenerIdentifier)
                 == AppOpsManager.MODE_ALLOWED;
     }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 34fb641..9bbe628 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -23,8 +23,11 @@
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
+import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
@@ -101,7 +104,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.EventLog;
-import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -116,7 +118,6 @@
 import com.android.internal.widget.ICheckCredentialProgressCallback;
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternUtils.CredentialType;
 import com.android.internal.widget.LockSettingsInternal;
 import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
@@ -178,7 +179,6 @@
 
     private static final int PROFILE_KEY_IV_SIZE = 12;
     private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
-    private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1;
     private static final String PREV_SYNTHETIC_PASSWORD_HANDLE_KEY = "prev-sp-handle";
     private static final String SYNTHETIC_PASSWORD_UPDATE_TIME_KEY = "sp-handle-ts";
 
@@ -317,14 +317,34 @@
         }
     }
 
+    private LockscreenCredential generateRandomProfilePassword() {
+        byte[] randomLockSeed = new byte[] {};
+        try {
+            randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
+            char[] newPasswordChars = HexEncoding.encode(randomLockSeed);
+            byte[] newPassword = new byte[newPasswordChars.length];
+            for (int i = 0; i < newPasswordChars.length; i++) {
+                newPassword[i] = (byte) newPasswordChars[i];
+            }
+            LockscreenCredential credential =
+                    LockscreenCredential.createManagedPassword(newPassword);
+            Arrays.fill(newPasswordChars, '\u0000');
+            Arrays.fill(newPassword, (byte) 0);
+            Arrays.fill(randomLockSeed, (byte) 0);
+            return credential;
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException("Fail to generate profile password", e);
+        }
+    }
+
     /**
      * Tie managed profile to primary profile if it is in unified mode and not tied before.
      *
      * @param managedUserId Managed profile user Id
      * @param managedUserPassword Managed profile original password (when it has separated lock).
-     *            NULL when it does not have a separated lock before.
      */
-    public void tieManagedProfileLockIfNecessary(int managedUserId, byte[] managedUserPassword) {
+    public void tieManagedProfileLockIfNecessary(int managedUserId,
+            LockscreenCredential managedUserPassword) {
         if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
         // Only for managed profile
         if (!mUserManager.getUserInfo(managedUserId).isManagedProfile()) {
@@ -356,27 +376,10 @@
             return;
         }
         if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
-        byte[] randomLockSeed = new byte[] {};
-        try {
-            randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
-            char[] newPasswordChars = HexEncoding.encode(randomLockSeed);
-            byte[] newPassword = new byte[newPasswordChars.length];
-            for (int i = 0; i < newPasswordChars.length; i++) {
-                newPassword[i] = (byte) newPasswordChars[i];
-            }
-            Arrays.fill(newPasswordChars, '\u0000');
-            final int quality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
-            setLockCredentialInternal(newPassword, CREDENTIAL_TYPE_PASSWORD, managedUserPassword,
-                    quality, managedUserId, false, /* isLockTiedToParent= */ true);
-            // We store a private credential for the managed user that's unlocked by the primary
-            // account holder's credential. As such, the user will never be prompted to enter this
-            // password directly, so we always store a password.
-            setLong(LockPatternUtils.PASSWORD_TYPE_KEY, quality, managedUserId);
-            tieProfileLockToParent(managedUserId, newPassword);
-            Arrays.fill(newPassword, (byte) 0);
-        } catch (NoSuchAlgorithmException e) {
-            Slog.e(TAG, "Fail to tie managed profile", e);
-            // Nothing client can do to fix this issue, so we do not throw exception out
+        try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
+            setLockCredentialInternal(unifiedProfilePassword, managedUserPassword, managedUserId,
+                    false, /* isLockTiedToParent= */ true);
+            tieProfileLockToParent(managedUserId, unifiedProfilePassword);
         }
     }
 
@@ -512,6 +515,10 @@
             }
         }
 
+        public int settingsGlobalGetInt(ContentResolver contentResolver, String keyName,
+                int defaultValue) {
+            return Settings.Global.getInt(contentResolver, keyName, defaultValue);
+        }
     }
 
     public LockSettingsService(Context context) {
@@ -682,7 +689,7 @@
                 hideEncryptionNotification(new UserHandle(userId));
 
                 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
-                    tieManagedProfileLockIfNecessary(userId, null);
+                    tieManagedProfileLockIfNecessary(userId, LockscreenCredential.createNone());
                 }
 
                 // If the user doesn't have a credential, try and derive their secret for the
@@ -704,10 +711,9 @@
             }
 
             final long handle = getSyntheticPasswordHandleLocked(userId);
-            final byte[] noCredential = null;
             AuthenticationResult result =
-                    mSpManager.unwrapPasswordBasedSyntheticPassword(
-                            getGateKeeperService(), handle, noCredential, userId, null);
+                    mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(),
+                            handle, LockscreenCredential.createNone(), userId, null);
             if (result.authToken != null) {
                 Slog.i(TAG, "Retrieved auth token for user " + userId);
                 onAuthTokenKnownForUser(userId, result.authToken);
@@ -870,25 +876,6 @@
         final List<UserInfo> users = mUserManager.getUsers();
         for (int i = 0; i < users.size(); i++) {
             final UserInfo userInfo = users.get(i);
-            if (userInfo.isManagedProfile() && mStorage.hasChildProfileLock(userInfo.id)) {
-                // When managed profile has a unified lock, the password quality stored has 2
-                // possibilities only.
-                // 1). PASSWORD_QUALITY_UNSPECIFIED, which is upgraded from dp2, and we are
-                // going to set it back to PASSWORD_QUALITY_ALPHANUMERIC.
-                // 2). PASSWORD_QUALITY_ALPHANUMERIC, which is the actual password quality for
-                // unified lock.
-                final long quality = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
-                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
-                if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
-                    // Only possible when it's upgraded from nyc dp3
-                    Slog.i(TAG, "Migrated tied profile lock type");
-                    setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
-                            DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, userInfo.id);
-                } else if (quality != DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) {
-                    // It should not happen
-                    Slog.e(TAG, "Invalid tied profile lock type: " + quality);
-                }
-            }
             try {
                 final String alias = LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userInfo.id;
                 java.security.KeyStore keyStore =
@@ -1031,21 +1018,22 @@
 
     @Override
     public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
-            byte[] managedUserPassword) {
+            LockscreenCredential managedUserPassword) {
         checkWritePermission(userId);
         if (!mLockPatternUtils.hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
                     "This operation requires secure lock screen feature.");
         }
         synchronized (mSeparateChallengeLock) {
-            setSeparateProfileChallengeEnabledLocked(userId, enabled, managedUserPassword);
+            setSeparateProfileChallengeEnabledLocked(userId, enabled, managedUserPassword != null
+                    ? managedUserPassword : LockscreenCredential.createNone());
         }
         notifySeparateProfileChallengeChanged(userId);
     }
 
     @GuardedBy("mSeparateChallengeLock")
     private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId,
-            boolean enabled, byte[] managedUserPassword) {
+            boolean enabled, LockscreenCredential managedUserPassword) {
         final boolean old = getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
         setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
         try {
@@ -1083,6 +1071,10 @@
     @Override
     public void setLong(String key, long value, int userId) {
         checkWritePermission(userId);
+        setLongUnchecked(key, value, userId);
+    }
+
+    private void setLongUnchecked(String key, long value, int userId) {
         setStringUnchecked(key, userId, Long.toString(value));
     }
 
@@ -1112,6 +1104,10 @@
     @Override
     public long getLong(String key, long defaultValue, int userId) {
         checkReadPermission(key, userId);
+        return getLongUnchecked(key, defaultValue, userId);
+    }
+
+    private long getLongUnchecked(String key, long defaultValue, int userId) {
         String value = getStringUnchecked(key, null, userId);
         return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
     }
@@ -1122,7 +1118,7 @@
         return getStringUnchecked(key, defaultValue, userId);
     }
 
-    public String getStringUnchecked(String key, String defaultValue, int userId) {
+    private String getStringUnchecked(String key, String defaultValue, int userId) {
         if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
             long ident = Binder.clearCallingIdentity();
             try {
@@ -1131,9 +1127,8 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
-
         if (userId == USER_FRP) {
-            return getFrpStringUnchecked(key);
+            return null;
         }
 
         if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
@@ -1143,51 +1138,81 @@
         return mStorage.readKeyValue(key, defaultValue, userId);
     }
 
-    private String getFrpStringUnchecked(String key) {
-        if (LockPatternUtils.PASSWORD_TYPE_KEY.equals(key)) {
-            return String.valueOf(readFrpPasswordQuality());
-        }
-        return null;
+    private void setKeyguardStoredQuality(int quality, int userId) {
+        if (DEBUG) Slog.d(TAG, "setKeyguardStoredQuality: user=" + userId + " quality=" + quality);
+        setLongUnchecked(LockPatternUtils.PASSWORD_TYPE_KEY, quality, userId);
     }
 
-    private int readFrpPasswordQuality() {
-        return mStorage.readPersistentDataBlock().qualityForUi;
+    private int getKeyguardStoredQuality(int userId) {
+        return (int) getLongUnchecked(LockPatternUtils.PASSWORD_TYPE_KEY,
+                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
     }
 
     @Override
-    public boolean havePassword(int userId) {
+    public int getCredentialType(int userId) {
         checkPasswordHavePermission(userId);
-        synchronized (mSpManager) {
-            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
-                final long handle = getSyntheticPasswordHandleLocked(userId);
-                return mSpManager.getCredentialType(handle, userId) == CREDENTIAL_TYPE_PASSWORD;
-            }
-        }
-        // Do we need a permissions check here?
-        return mStorage.hasPassword(userId);
+        return getCredentialTypeInternal(userId);
     }
 
-    @Override
-    public boolean havePattern(int userId) {
-        checkPasswordHavePermission(userId);
+    // TODO: this is a hot path, can we optimize it?
+    /**
+     * Returns the credential type of the user, can be one of {@link #CREDENTIAL_TYPE_NONE},
+     * {@link #CREDENTIAL_TYPE_PATTERN}, {@link #CREDENTIAL_TYPE_PIN} and
+     * {@link #CREDENTIAL_TYPE_PASSWORD}
+     */
+    public int getCredentialTypeInternal(int userId) {
+        if (userId == USER_FRP) {
+            return getFrpCredentialType();
+        }
         synchronized (mSpManager) {
             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
                 final long handle = getSyntheticPasswordHandleLocked(userId);
-                return mSpManager.getCredentialType(handle, userId) == CREDENTIAL_TYPE_PATTERN;
+                int rawType = mSpManager.getCredentialType(handle, userId);
+                if (rawType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
+                    return rawType;
+                }
+                return pinOrPasswordQualityToCredentialType(getKeyguardStoredQuality(userId));
             }
         }
-        // Do we need a permissions check here?
-        return mStorage.hasPattern(userId);
+        // Intentional duplication of the getKeyguardStoredQuality() call above since this is a
+        // unlikely code path (device with pre-synthetic password credential). We want to skip
+        // calling getKeyguardStoredQuality whenever possible.
+        final int savedQuality = getKeyguardStoredQuality(userId);
+        if (savedQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
+                && mStorage.hasPattern(userId)) {
+            return CREDENTIAL_TYPE_PATTERN;
+        }
+        if (savedQuality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
+                && mStorage.hasPassword(userId)) {
+            return pinOrPasswordQualityToCredentialType(savedQuality);
+        }
+        return CREDENTIAL_TYPE_NONE;
+    }
+
+    private int getFrpCredentialType() {
+        PersistentData data = mStorage.readPersistentDataBlock();
+        if (data.type != PersistentData.TYPE_SP && data.type != PersistentData.TYPE_SP_WEAVER) {
+            return CREDENTIAL_TYPE_NONE;
+        }
+        int credentialType = SyntheticPasswordManager.getFrpCredentialType(data.payload);
+        if (credentialType != CREDENTIAL_TYPE_PASSWORD_OR_PIN) {
+            return credentialType;
+        }
+        return pinOrPasswordQualityToCredentialType(data.qualityForUi);
+    }
+
+    private static int pinOrPasswordQualityToCredentialType(int quality) {
+        if (LockPatternUtils.isQualityAlphabeticPassword(quality)) {
+            return CREDENTIAL_TYPE_PASSWORD;
+        }
+        if (LockPatternUtils.isQualityNumericPin(quality)) {
+            return CREDENTIAL_TYPE_PIN;
+        }
+        throw new IllegalArgumentException("Quality is neither Pin nor password: " + quality);
     }
 
     private boolean isUserSecure(int userId) {
-        synchronized (mSpManager) {
-            if (isSyntheticPasswordBasedCredentialLocked(userId)) {
-                final long handle = getSyntheticPasswordHandleLocked(userId);
-                return mSpManager.getCredentialType(handle, userId) != CREDENTIAL_TYPE_NONE;
-            }
-        }
-        return mStorage.hasCredential(userId);
+        return getCredentialTypeInternal(userId) != CREDENTIAL_TYPE_NONE;
     }
 
     private void setKeystorePassword(byte[] password, int userHandle) {
@@ -1205,8 +1230,8 @@
         ks.unlock(userHandle, passwordString);
     }
 
-    @VisibleForTesting
-    protected byte[] getDecryptedPasswordForTiedProfile(int userId)
+    @VisibleForTesting /** Note: this method is overridden in unit tests */
+    protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId)
             throws KeyStoreException, UnrecoverableKeyException,
             NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
             InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
@@ -1230,7 +1255,10 @@
 
         cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
         decryptionResult = cipher.doFinal(encryptedPassword);
-        return decryptionResult;
+        LockscreenCredential credential = LockscreenCredential.createManagedPassword(
+                decryptionResult);
+        Arrays.fill(decryptionResult, (byte) 0);
+        return credential;
     }
 
     private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated,
@@ -1238,7 +1266,6 @@
             @Nullable ArrayList<PendingResetLockout> resetLockouts) {
         try {
             doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
-                    CREDENTIAL_TYPE_PASSWORD,
                     challengeType, challenge, profileHandle, null /* progressCallback */,
                     resetLockouts);
         } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
@@ -1276,17 +1303,17 @@
         final IProgressListener listener = new IProgressListener.Stub() {
             @Override
             public void onStarted(int id, Bundle extras) throws RemoteException {
-                Log.d(TAG, "unlockUser started");
+                Slog.d(TAG, "unlockUser started");
             }
 
             @Override
             public void onProgress(int id, int progress, Bundle extras) throws RemoteException {
-                Log.d(TAG, "unlockUser progress " + progress);
+                Slog.d(TAG, "unlockUser progress " + progress);
             }
 
             @Override
             public void onFinished(int id, Bundle extras) throws RemoteException {
-                Log.d(TAG, "unlockUser finished");
+                Slog.d(TAG, "unlockUser finished");
                 latch.countDown();
             }
         };
@@ -1351,11 +1378,11 @@
                 && mUserManager.isUserRunning(userInfo.id);
     }
 
-    private Map<Integer, byte[]> getDecryptedPasswordsForAllTiedProfiles(int userId) {
+    private Map<Integer, LockscreenCredential> getDecryptedPasswordsForAllTiedProfiles(int userId) {
         if (mUserManager.getUserInfo(userId).isManagedProfile()) {
             return null;
         }
-        Map<Integer, byte[]> result = new ArrayMap<Integer, byte[]>();
+        Map<Integer, LockscreenCredential> result = new ArrayMap<>();
         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
         final int size = profiles.size();
         for (int i = 0; i < size; i++) {
@@ -1393,7 +1420,7 @@
      * terminates when the user is a managed profile.
      */
     private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
-            Map<Integer, byte[]> profilePasswordMap) {
+            Map<Integer, LockscreenCredential> profilePasswordMap) {
         if (mUserManager.getUserInfo(userId).isManagedProfile()) {
             return;
         }
@@ -1408,20 +1435,23 @@
                     continue;
                 }
                 if (isSecure) {
-                    tieManagedProfileLockIfNecessary(managedUserId, null);
+                    tieManagedProfileLockIfNecessary(managedUserId,
+                            LockscreenCredential.createNone());
                 } else {
                     // We use cached work profile password computed before clearing the parent's
                     // credential, otherwise they get lost
-                    if (profilePasswordMap != null && profilePasswordMap.containsKey(managedUserId)) {
-                        setLockCredentialInternal(null, CREDENTIAL_TYPE_NONE,
+                    if (profilePasswordMap != null
+                            && profilePasswordMap.containsKey(managedUserId)) {
+                        setLockCredentialInternal(LockscreenCredential.createNone(),
                                 profilePasswordMap.get(managedUserId),
-                                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId,
+                                managedUserId,
                                 false, /* isLockTiedToParent= */ true);
                     } else {
                         Slog.wtf(TAG, "clear tied profile challenges, but no password supplied.");
-                        // Supplying null here would lead to untrusted credential change
-                        setLockCredentialInternal(null, CREDENTIAL_TYPE_NONE, null,
-                                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, managedUserId,
+                        // Attempt an untrusted reset by supplying an empty credential.
+                        setLockCredentialInternal(LockscreenCredential.createNone(),
+                                LockscreenCredential.createNone(),
+                                managedUserId,
                                 true, /* isLockTiedToParent= */ true);
                     }
                     mStorage.removeChildProfileLock(managedUserId);
@@ -1445,8 +1475,7 @@
      * Send credentials for user {@code userId} to {@link RecoverableKeyStoreManager} during an
      * unlock operation.
      */
-    private void sendCredentialsOnUnlockIfRequired(
-            int credentialType, @NonNull byte[] credential, int userId) {
+    private void sendCredentialsOnUnlockIfRequired(LockscreenCredential credential, int userId) {
         // Don't send credentials during the factory reset protection flow.
         if (userId == USER_FRP) {
             return;
@@ -1459,10 +1488,12 @@
             return;
         }
 
+        // RecoverableKeyStoreManager expects null for empty credential.
+        final byte[] secret = credential.isNone() ? null : credential.getCredential();
         // Send credentials for the user and any child profiles that share its lock screen.
         for (int profileId : getProfilesWithSameLockScreen(userId)) {
             mRecoverableKeyStoreManager.lockScreenSecretAvailable(
-                    credentialType, credential, profileId);
+                    credential.getType(), secret, profileId);
         }
     }
 
@@ -1471,7 +1502,7 @@
      * credentials are set/changed.
      */
     private void sendCredentialsOnChangeIfRequired(
-            int credentialType, byte[] credential, int userId, boolean isLockTiedToParent) {
+            LockscreenCredential credential, int userId, boolean isLockTiedToParent) {
         // A profile whose lock screen is being tied to its parent's will either have a randomly
         // generated credential (creation) or null (removal). We rely on the parent to send its
         // credentials for the profile in both cases as it stores the unified lock credential.
@@ -1479,10 +1510,12 @@
             return;
         }
 
+        // RecoverableKeyStoreManager expects null for empty credential.
+        final byte[] secret = credential.isNone() ? null : credential.getCredential();
         // Send credentials for the user and any child profiles that share its lock screen.
         for (int profileId : getProfilesWithSameLockScreen(userId)) {
             mRecoverableKeyStoreManager.lockScreenSecretChanged(
-                    credentialType, credential, profileId);
+                    credential.getType(), secret, profileId);
         }
     }
 
@@ -1505,9 +1538,8 @@
     // This method should be called by LockPatternUtil only, all internal methods in this class
     // should call setLockCredentialInternal.
     @Override
-    public boolean setLockCredential(byte[] credential, int type,
-            byte[] savedCredential, int requestedQuality, int userId,
-            boolean allowUntrustedChange) {
+    public boolean setLockCredential(LockscreenCredential credential,
+            LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange) {
 
         if (!mLockPatternUtils.hasSecureLockScreen()) {
             throw new UnsupportedOperationException(
@@ -1515,11 +1547,11 @@
         }
         checkWritePermission(userId);
         synchronized (mSeparateChallengeLock) {
-            if (!setLockCredentialInternal(credential, type, savedCredential, requestedQuality,
+            if (!setLockCredentialInternal(credential, savedCredential,
                     userId, allowUntrustedChange, /* isLockTiedToParent= */ false)) {
                 return false;
             }
-            setSeparateProfileChallengeEnabledLocked(userId, true, null);
+            setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
             notifyPasswordChanged(userId);
         }
         if (mUserManager.getUserInfo(userId).isManagedProfile()) {
@@ -1531,51 +1563,44 @@
     }
 
     /**
+     * @param savedCredential if the user is a managed profile with unified challenge and
+     *   savedCredential is empty, LSS will try to re-derive the profile password internally.
+     *     TODO (b/80170828): Fix this so profile password is always passed in.
      * @param isLockTiedToParent is {@code true} if {@code userId} is a profile and its new
      *     credentials are being tied to its parent's credentials.
      */
-    private boolean setLockCredentialInternal(byte[] credential, @CredentialType int credentialType,
-            byte[] savedCredential, int requestedQuality, int userId, boolean allowUntrustedChange,
-            boolean isLockTiedToParent) {
-        // Normalize savedCredential and credential such that empty string is always represented
-        // as null.
-        if (savedCredential == null || savedCredential.length == 0) {
-            savedCredential = null;
-        }
-        if (credential == null || credential.length == 0) {
-            credential = null;
-        }
+    private boolean setLockCredentialInternal(LockscreenCredential credential,
+            LockscreenCredential savedCredential, int userId,
+            boolean allowUntrustedChange, boolean isLockTiedToParent) {
+        Preconditions.checkNotNull(credential);
+        Preconditions.checkNotNull(savedCredential);
         synchronized (mSpManager) {
             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
-                return spBasedSetLockCredentialInternalLocked(credential, credentialType,
-                        savedCredential, requestedQuality, userId, allowUntrustedChange,
-                        isLockTiedToParent);
+                return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
+                        allowUntrustedChange, isLockTiedToParent);
             }
         }
 
-        if (credentialType == CREDENTIAL_TYPE_NONE) {
-            if (credential != null) {
-                Slog.wtf(TAG, "CredentialType is none, but credential is non-null.");
-            }
+        if (credential.isNone()) {
             clearUserKeyProtection(userId);
             gateKeeperClearSecureUserId(userId);
             mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
+            // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
+            // since it forms part of the state that determines the credential type
+            // @see getCredentialTypeInternal
+            setKeyguardStoredQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
             setKeystorePassword(null, userId);
             fixateNewestUserKeyAuth(userId);
             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
-            setUserPasswordMetrics(CREDENTIAL_TYPE_NONE, null, userId);
-            sendCredentialsOnChangeIfRequired(
-                    credentialType, credential, userId, isLockTiedToParent);
+            setUserPasswordMetrics(LockscreenCredential.createNone(), userId);
+            sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
             return true;
         }
-        if (credential == null) {
-            throw new IllegalArgumentException("Null credential with mismatched credential type");
-        }
 
         CredentialHash currentHandle = mStorage.readCredentialHash(userId);
         if (isManagedProfileWithUnifiedLock(userId)) {
             // get credential from keystore when managed profile has unified lock
-            if (savedCredential == null) {
+            if (savedCredential.isNone()) {
                 try {
                     savedCredential = getDecryptedPasswordForTiedProfile(userId);
                 } catch (FileNotFoundException e) {
@@ -1589,47 +1614,50 @@
             }
         } else {
             if (currentHandle.hash == null) {
-                if (savedCredential != null) {
+                if (!savedCredential.isNone()) {
                     Slog.w(TAG, "Saved credential provided, but none stored");
                 }
-                savedCredential = null;
+                savedCredential.close();
+                savedCredential = LockscreenCredential.createNone();
             }
         }
         synchronized (mSpManager) {
             if (shouldMigrateToSyntheticPasswordLocked(userId)) {
-                initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential,
-                        currentHandle.type, requestedQuality, userId);
-                return spBasedSetLockCredentialInternalLocked(credential, credentialType,
-                        savedCredential, requestedQuality, userId, allowUntrustedChange,
-                        isLockTiedToParent);
+                initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, userId);
+                return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
+                        allowUntrustedChange, isLockTiedToParent);
             }
         }
         if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
-        byte[] enrolledHandle = enrollCredential(currentHandle.hash, savedCredential, credential,
-                userId);
+        byte[] enrolledHandle = enrollCredential(currentHandle.hash,
+                savedCredential.getCredential(), credential.getCredential(), userId);
         if (enrolledHandle == null) {
             Slog.w(TAG, String.format("Failed to enroll %s: incorrect credential",
-                    credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern"));
+                    credential.isPattern() ? "pattern" : "password"));
             return false;
         }
-        CredentialHash willStore = CredentialHash.create(enrolledHandle, credentialType);
+        CredentialHash willStore = CredentialHash.create(enrolledHandle, credential.getType());
         mStorage.writeCredentialHash(willStore, userId);
+        // Still update PASSWORD_TYPE_KEY if we are running in pre-synthetic password code path,
+        // since it forms part of the state that determines the credential type
+        // @see getCredentialTypeInternal
+        setKeyguardStoredQuality(
+                LockPatternUtils.credentialTypeToPasswordQuality(credential.getType()), userId);
         // push new secret and auth token to vold
         GateKeeperResponse gkResponse;
         try {
             gkResponse = getGateKeeperService().verifyChallenge(userId, 0, willStore.hash,
-                    credential);
+                    credential.getCredential());
         } catch (RemoteException e) {
             throw new IllegalStateException("Failed to verify current credential", e);
         }
         setUserKeyProtection(userId, credential, convertResponse(gkResponse));
         fixateNewestUserKeyAuth(userId);
         // Refresh the auth token
-        doVerifyCredential(credential, credentialType, CHALLENGE_FROM_CALLER, 0, userId,
+        doVerifyCredential(credential, CHALLENGE_FROM_CALLER, 0, userId,
                 null /* progressCallback */);
         synchronizeUnifiedWorkChallengeForProfiles(userId, null);
-        sendCredentialsOnChangeIfRequired(
-                credentialType, credential, userId, isLockTiedToParent);
+        sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
         return true;
     }
 
@@ -1637,8 +1665,8 @@
         return VerifyCredentialResponse.fromGateKeeperResponse(gateKeeperResponse);
     }
 
-    @VisibleForTesting
-    protected void tieProfileLockToParent(int userId, byte[] password) {
+    @VisibleForTesting /** Note: this method is overridden in unit tests */
+    protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
         if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
         byte[] encryptionResult;
         byte[] iv;
@@ -1673,7 +1701,7 @@
                         KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
                                 + KeyProperties.ENCRYPTION_PADDING_NONE);
                 cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
-                encryptionResult = cipher.doFinal(password);
+                encryptionResult = cipher.doFinal(password.getCredential());
                 iv = cipher.getIV();
             } finally {
                 // The original key can now be discarded.
@@ -1728,7 +1756,8 @@
         addUserKeyAuth(userId, null, key);
     }
 
-    private void setUserKeyProtection(int userId, byte[] credential, VerifyCredentialResponse vcr) {
+    private void setUserKeyProtection(int userId, LockscreenCredential credential,
+            VerifyCredentialResponse vcr) {
         if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId);
         if (vcr == null) {
             throw new IllegalArgumentException("Null response verifying a credential we just set");
@@ -1749,7 +1778,7 @@
         addUserKeyAuth(userId, null, null);
     }
 
-    private static byte[] secretFromCredential(byte[] credential) {
+    private static byte[] secretFromCredential(LockscreenCredential credential) {
         try {
             MessageDigest digest = MessageDigest.getInstance("SHA-512");
             // Personalize the hash
@@ -1757,7 +1786,7 @@
             // Pad it to the block size of the hash function
             personalization = Arrays.copyOf(personalization, 128);
             digest.update(personalization);
-            digest.update(credential);
+            digest.update(credential.getCredential());
             return digest.digest();
         } catch (NoSuchAlgorithmException e) {
             throw new IllegalStateException("NoSuchAlgorithmException for SHA-512");
@@ -1768,7 +1797,7 @@
         try {
             return mStorageManager.isUserKeyUnlocked(userId);
         } catch (RemoteException e) {
-            Log.e(TAG, "failed to check user key locked state", e);
+            Slog.e(TAG, "failed to check user key locked state", e);
             return false;
         }
     }
@@ -1815,7 +1844,7 @@
         checkWritePermission(userId);
         if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
         int managedUserId = -1;
-        byte[] managedUserDecryptedPassword = null;
+        LockscreenCredential managedUserDecryptedPassword = null;
         final List<UserInfo> profiles = mUserManager.getProfiles(userId);
         for (UserInfo pi : profiles) {
             // Unlock managed profile with unified lock
@@ -1852,30 +1881,30 @@
                 tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
             }
         }
-        if (managedUserDecryptedPassword != null && managedUserDecryptedPassword.length > 0) {
-            Arrays.fill(managedUserDecryptedPassword, (byte) 0);
+        if (managedUserDecryptedPassword != null) {
+            managedUserDecryptedPassword.zeroize();
         }
     }
 
     @Override
-    public VerifyCredentialResponse checkCredential(byte[] credential, int type, int userId,
+    public VerifyCredentialResponse checkCredential(LockscreenCredential credential, int userId,
             ICheckCredentialProgressCallback progressCallback) {
         checkPasswordReadPermission(userId);
-        return doVerifyCredential(credential, type, CHALLENGE_NONE, 0, userId, progressCallback);
+        return doVerifyCredential(credential, CHALLENGE_NONE, 0, userId, progressCallback);
     }
 
     @Override
-    public VerifyCredentialResponse verifyCredential(byte[] credential, int type, long challenge,
-            int userId) {
+    public VerifyCredentialResponse verifyCredential(LockscreenCredential credential,
+            long challenge, int userId) {
         checkPasswordReadPermission(userId);
-        return doVerifyCredential(credential, type, CHALLENGE_FROM_CALLER, challenge, userId,
+        return doVerifyCredential(credential, CHALLENGE_FROM_CALLER, challenge, userId,
                 null /* progressCallback */);
     }
 
-    private VerifyCredentialResponse doVerifyCredential(byte[] credential, int credentialType,
+    private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
             @ChallengeType int challengeType, long challenge, int userId,
             ICheckCredentialProgressCallback progressCallback) {
-        return doVerifyCredential(credential, credentialType, challengeType, challenge, userId,
+        return doVerifyCredential(credential, challengeType, challenge, userId,
                 progressCallback, null /* resetLockouts */);
     }
 
@@ -1883,25 +1912,25 @@
      * Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero
      * format.
      */
-    private VerifyCredentialResponse doVerifyCredential(byte[] credential, int credentialType,
+    private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
             @ChallengeType int challengeType, long challenge, int userId,
             ICheckCredentialProgressCallback progressCallback,
             @Nullable ArrayList<PendingResetLockout> resetLockouts) {
-        if (credential == null || credential.length == 0) {
+        if (credential == null || credential.isNone()) {
             throw new IllegalArgumentException("Credential can't be null or empty");
         }
-        if (userId == USER_FRP && Settings.Global.getInt(mContext.getContentResolver(),
+        if (userId == USER_FRP && mInjector.settingsGlobalGetInt(mContext.getContentResolver(),
                 Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
             Slog.e(TAG, "FRP credential can only be verified prior to provisioning.");
             return VerifyCredentialResponse.ERROR;
         }
         VerifyCredentialResponse response = null;
-        response = spBasedDoVerifyCredential(credential, credentialType, challengeType, challenge,
+        response = spBasedDoVerifyCredential(credential, challengeType, challenge,
                 userId, progressCallback, resetLockouts);
         // The user employs synthetic password based credential.
         if (response != null) {
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
-                sendCredentialsOnUnlockIfRequired(credentialType, credential, userId);
+                sendCredentialsOnUnlockIfRequired(credential, userId);
             }
             return response;
         }
@@ -1912,9 +1941,9 @@
         }
 
         final CredentialHash storedHash = mStorage.readCredentialHash(userId);
-        if (storedHash.type != credentialType) {
+        if (!credential.checkAgainstStoredType(storedHash.type)) {
             Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??"
-                    + " stored: " + storedHash.type + " passed in: " + credentialType);
+                    + " stored: " + storedHash.type + " passed in: " + credential.getType());
             return VerifyCredentialResponse.ERROR;
         }
 
@@ -1929,7 +1958,7 @@
     }
 
     @Override
-    public VerifyCredentialResponse verifyTiedProfileChallenge(byte[] credential, int type,
+    public VerifyCredentialResponse verifyTiedProfileChallenge(LockscreenCredential credential,
             long challenge, int userId) {
         checkPasswordReadPermission(userId);
         if (!isManagedProfileWithUnifiedLock(userId)) {
@@ -1939,7 +1968,6 @@
         // Unlock parent by using parent's challenge
         final VerifyCredentialResponse parentResponse = doVerifyCredential(
                 credential,
-                type,
                 CHALLENGE_FROM_CALLER,
                 challenge,
                 parentProfileId,
@@ -1952,7 +1980,6 @@
         try {
             // Unlock work profile, and work profile with unified lock must use password only
             return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
-                    CREDENTIAL_TYPE_PASSWORD,
                     CHALLENGE_FROM_CALLER,
                     challenge,
                     userId, null /* progressCallback */);
@@ -1971,15 +1998,14 @@
      * hash to GK.
      */
     private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
-            byte[] credential, @ChallengeType int challengeType, long challenge,
+            LockscreenCredential credential, @ChallengeType int challengeType, long challenge,
             ICheckCredentialProgressCallback progressCallback) {
-        if ((storedHash == null || storedHash.hash.length == 0)
-                    && (credential == null || credential.length == 0)) {
+        if ((storedHash == null || storedHash.hash.length == 0) && credential.isNone()) {
             // don't need to pass empty credentials to GateKeeper
             return VerifyCredentialResponse.OK;
         }
 
-        if (storedHash == null || credential == null || credential.length == 0) {
+        if (storedHash == null || storedHash.hash.length == 0 || credential.isNone()) {
             return VerifyCredentialResponse.ERROR;
         }
 
@@ -1989,8 +2015,8 @@
 
         GateKeeperResponse gateKeeperResponse;
         try {
-            gateKeeperResponse = getGateKeeperService()
-                    .verifyChallenge(userId, challenge, storedHash.hash, credential);
+            gateKeeperResponse = getGateKeeperService().verifyChallenge(
+                    userId, challenge, storedHash.hash, credential.getCredential());
         } catch (RemoteException e) {
             Slog.e(TAG, "gatekeeper verify failed", e);
             gateKeeperResponse = GateKeeperResponse.ERROR;
@@ -2006,11 +2032,11 @@
                 try {
                     progressCallback.onCredentialVerified();
                 } catch (RemoteException e) {
-                    Log.w(TAG, "progressCallback throws exception", e);
+                    Slog.w(TAG, "progressCallback throws exception", e);
                 }
             }
-            setUserPasswordMetrics(storedHash.type, credential, userId);
-            unlockKeystore(credential, userId);
+            setUserPasswordMetrics(credential, userId);
+            unlockKeystore(credential.getCredential(), userId);
 
             Slog.i(TAG, "Unlocking user " + userId + " with token length "
                     + response.getPayload().length);
@@ -2019,27 +2045,22 @@
             if (isManagedProfileWithSeparatedLock(userId)) {
                 setDeviceUnlockedForUser(userId);
             }
-            int reEnrollQuality = storedHash.type == CREDENTIAL_TYPE_PATTERN
-                    ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
-                    : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
-                    /* TODO(roosa): keep the same password quality */;
             if (shouldReEnroll) {
-                setLockCredentialInternal(credential, storedHash.type, credential,
-                        reEnrollQuality, userId, false, /* isLockTiedToParent= */ false);
+                setLockCredentialInternal(credential, credential,
+                        userId, false, /* isLockTiedToParent= */ false);
             } else {
                 // Now that we've cleared of all required GK migration, let's do the final
                 // migration to synthetic password.
                 synchronized (mSpManager) {
                     if (shouldMigrateToSyntheticPasswordLocked(userId)) {
                         AuthenticationToken auth = initializeSyntheticPasswordLocked(
-                                storedHash.hash, credential, storedHash.type, reEnrollQuality,
-                                userId);
+                                storedHash.hash, credential,  userId);
                         activateEscrowTokens(auth, userId);
                     }
                 }
             }
             // Use credentials to create recoverable keystore snapshot.
-            sendCredentialsOnUnlockIfRequired(storedHash.type, credential, userId);
+            sendCredentialsOnUnlockIfRequired(credential, userId);
 
         } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
             if (response.getTimeout() > 0) {
@@ -2055,12 +2076,9 @@
      * when the user is authenticating or when a new password is being set. In comparison,
      * {@link #notifyPasswordChanged} only needs to be called when the user changes the password.
      */
-    private void setUserPasswordMetrics(@CredentialType int credentialType, byte[] password,
-            @UserIdInt int userHandle) {
+    private void setUserPasswordMetrics(LockscreenCredential password, @UserIdInt int userHandle) {
         synchronized (this) {
-            mUserPasswordMetrics.put(userHandle,
-                    PasswordMetrics.computeForCredential(
-                            LockscreenCredential.createRaw(credentialType, password)));
+            mUserPasswordMetrics.put(userHandle, PasswordMetrics.computeForCredential(password));
         }
     }
 
@@ -2089,6 +2107,14 @@
         });
     }
 
+    private LockscreenCredential createPattern(String patternString) {
+        final byte[] patternBytes = patternString.getBytes();
+        LockscreenCredential pattern = LockscreenCredential.createPattern(
+                LockPatternUtils.byteArrayToPattern(patternBytes));
+        Arrays.fill(patternBytes, (byte) 0);
+        return pattern;
+    }
+
     @Override
     public boolean checkVoldPassword(int userId) {
         if (!mFirstCallToVold) {
@@ -2119,30 +2145,34 @@
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
-        if (password == null) {
+        if (TextUtils.isEmpty(password)) {
             return false;
         }
 
         try {
-            if (mLockPatternUtils.isLockPatternEnabled(userId)) {
-                if (checkCredential(password.getBytes(), CREDENTIAL_TYPE_PATTERN,
-                        userId, null /* progressCallback */)
-                                .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
-                    return true;
-                }
+            final LockscreenCredential credential;
+            switch (getCredentialTypeInternal(userId)) {
+                case CREDENTIAL_TYPE_PATTERN:
+                    credential = createPattern(password);
+                    break;
+                case CREDENTIAL_TYPE_PIN:
+                    credential = LockscreenCredential.createPin(password);
+                    break;
+                case CREDENTIAL_TYPE_PASSWORD:
+                    credential = LockscreenCredential.createPassword(password);
+                    break;
+                default:
+                    credential = null;
+                    Slog.e(TAG, "Unknown credential type");
             }
-        } catch (Exception e) {
-        }
 
-        try {
-            if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
-                if (checkCredential(password.getBytes(), CREDENTIAL_TYPE_PASSWORD,
-                        userId, null /* progressCallback */)
+            if (credential != null
+                    && checkCredential(credential, userId, null /* progressCallback */)
                                 .getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
-                    return true;
-                }
+                return true;
             }
         } catch (Exception e) {
+            Slog.e(TAG, "checkVoldPassword failed: ", e);
         }
 
         return false;
@@ -2524,7 +2554,7 @@
     @GuardedBy("mSpManager")
     @VisibleForTesting
     protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
-            byte[] credential, int credentialType, int requestedQuality, int userId) {
+            LockscreenCredential credential, int userId) {
         Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
         final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(
                 getGateKeeperService(), credentialHash, credential, userId);
@@ -2534,8 +2564,8 @@
             return null;
         }
         long handle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
-                credential, credentialType, auth, requestedQuality, userId);
-        if (credential != null) {
+                credential, auth, userId);
+        if (!credential.isNone()) {
             if (credentialHash == null) {
                 // Since when initializing SP, we didn't provide an existing password handle
                 // for it to migrate SID, we need to create a new SID for the user.
@@ -2567,6 +2597,13 @@
 
     }
 
+    @VisibleForTesting
+    boolean isSyntheticPasswordBasedCredential(int userId) {
+        synchronized (mSpManager) {
+            return isSyntheticPasswordBasedCredentialLocked(userId);
+        }
+    }
+
     private boolean isSyntheticPasswordBasedCredentialLocked(int userId) {
         if (userId == USER_FRP) {
             final int type = mStorage.readPersistentDataBlock().type;
@@ -2592,8 +2629,8 @@
         setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
     }
 
-    private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential,
-            @CredentialType int credentialType, @ChallengeType int challengeType, long challenge,
+    private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential,
+            @ChallengeType int challengeType, long challenge,
             int userId, ICheckCredentialProgressCallback progressCallback,
             @Nullable ArrayList<PendingResetLockout> resetLockouts) {
 
@@ -2601,9 +2638,6 @@
 
         Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId + " challengeType=" + challengeType
                 + " hasEnrolledBiometrics=" + hasEnrolledBiometrics);
-        if (credentialType == CREDENTIAL_TYPE_NONE) {
-            userCredential = null;
-        }
 
         final PackageManager pm = mContext.getPackageManager();
         // TODO: When lockout is handled under the HAL for all biometrics (fingerprint),
@@ -2625,17 +2659,13 @@
             }
             if (userId == USER_FRP) {
                 return mSpManager.verifyFrpCredential(getGateKeeperService(),
-                        userCredential, credentialType, progressCallback);
+                        userCredential, progressCallback);
             }
 
             long handle = getSyntheticPasswordHandleLocked(userId);
             authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
                     getGateKeeperService(), handle, userCredential, userId, progressCallback);
 
-            if (authResult.credentialType != credentialType) {
-                Slog.e(TAG, "Credential type mismatch.");
-                return VerifyCredentialResponse.ERROR;
-            }
             response = authResult.gkResponse;
             // credential has matched
             if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
@@ -2653,7 +2683,7 @@
         }
 
         if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
-            setUserPasswordMetrics(credentialType, userCredential, userId);
+            setUserPasswordMetrics(userCredential, userId);
             unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
 
             // Do resetLockout / revokeChallenge when all profiles are unlocked
@@ -2700,14 +2730,13 @@
      * added back when new password is set in future.
      */
     @GuardedBy("mSpManager")
-    private long setLockCredentialWithAuthTokenLocked(byte[] credential,
-            @CredentialType int credentialType, AuthenticationToken auth, int requestedQuality,
-            int userId) {
+    private long setLockCredentialWithAuthTokenLocked(LockscreenCredential credential,
+            AuthenticationToken auth, int userId) {
         if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
         long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
-                credential, credentialType, auth, requestedQuality, userId);
-        final Map<Integer, byte[]> profilePasswords;
-        if (credential != null) {
+                credential, auth, userId);
+        final Map<Integer, LockscreenCredential> profilePasswords;
+        if (!credential.isNone()) {
             // not needed by synchronizeUnifiedWorkChallengeForProfiles()
             profilePasswords = null;
 
@@ -2748,11 +2777,11 @@
         setSyntheticPasswordHandleLocked(newHandle, userId);
         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
 
-        setUserPasswordMetrics(credentialType, credential, userId);
+        setUserPasswordMetrics(credential, userId);
 
         if (profilePasswords != null) {
-            for (Map.Entry<Integer, byte[]> entry : profilePasswords.entrySet()) {
-                Arrays.fill(entry.getValue(), (byte) 0);
+            for (Map.Entry<Integer, LockscreenCredential> entry : profilePasswords.entrySet()) {
+                entry.getValue().zeroize();
             }
         }
 
@@ -2838,12 +2867,17 @@
         };
     }
 
+    /**
+     * @param savedCredential if the user is a managed profile with unified challenge and
+     *   savedCredential is empty, LSS will try to re-derive the profile password internally.
+     *     TODO (b/80170828): Fix this so profile password is always passed in.
+     */
     @GuardedBy("mSpManager")
-    private boolean spBasedSetLockCredentialInternalLocked(byte[] credential, int credentialType,
-            byte[] savedCredential, int requestedQuality, int userId,
+    private boolean spBasedSetLockCredentialInternalLocked(LockscreenCredential credential,
+            LockscreenCredential savedCredential, int userId,
             boolean allowUntrustedChange, boolean isLockTiedToParent) {
         if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
-        if (isManagedProfileWithUnifiedLock(userId)) {
+        if (savedCredential.isNone() && isManagedProfileWithUnifiedLock(userId)) {
             // get credential from keystore when managed profile has unified lock
             try {
                 savedCredential = getDecryptedPasswordForTiedProfile(userId);
@@ -2863,9 +2897,8 @@
         AuthenticationToken auth = authResult.authToken;
 
         // If existing credential is provided, the existing credential must match.
-        if (savedCredential != null && auth == null) {
-            Slog.w(TAG, String.format("Failed to enroll %s: incorrect credential",
-                    credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern"));
+        if (!savedCredential.isNone() && auth == null) {
+            Slog.w(TAG, "Failed to enroll: incorrect credential");
             return false;
         }
         boolean untrustedReset = false;
@@ -2898,8 +2931,7 @@
                 // setLockCredentialWithAuthTokenLocked next
                 mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
             }
-            setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, requestedQuality,
-                    userId);
+            setLockCredentialWithAuthTokenLocked(credential, auth, userId);
             mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
         } else {
             throw new IllegalStateException(
@@ -2908,7 +2940,7 @@
             // requestedQuality, userId) instead if we still allow untrusted reset that changes
             // synthetic password. That would invalidate existing escrow tokens though.
         }
-        sendCredentialsOnChangeIfRequired(credentialType, credential, userId, isLockTiedToParent);
+        sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
         return true;
     }
 
@@ -2919,11 +2951,8 @@
      * If user is a managed profile with unified challenge, currentCredential is ignored.
      */
     @Override
-    public byte[] getHashFactor(byte[] currentCredential, int userId) {
+    public byte[] getHashFactor(LockscreenCredential currentCredential, int userId) {
         checkPasswordReadPermission(userId);
-        if (currentCredential == null || currentCredential.length == 0) {
-            currentCredential = null;
-        }
         if (isManagedProfileWithUnifiedLock(userId)) {
             try {
                 currentCredential = getDecryptedPasswordForTiedProfile(userId);
@@ -2957,13 +2986,12 @@
             AuthenticationToken auth = null;
             if (!isUserSecure(userId)) {
                 if (shouldMigrateToSyntheticPasswordLocked(userId)) {
-                    auth = initializeSyntheticPasswordLocked(null, null,
-                            CREDENTIAL_TYPE_NONE,
-                            DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
+                    auth = initializeSyntheticPasswordLocked(
+                            /* credentialHash */ null, LockscreenCredential.createNone(), userId);
                 } else /* isSyntheticPasswordBasedCredentialLocked(userId) */ {
                     long pwdHandle = getSyntheticPasswordHandleLocked(userId);
                     auth = mSpManager.unwrapPasswordBasedSyntheticPassword(getGateKeeperService(),
-                            pwdHandle, null, userId, null).authToken;
+                            pwdHandle, LockscreenCredential.createNone(), userId, null).authToken;
                 }
             }
             if (isSyntheticPasswordBasedCredentialLocked(userId)) {
@@ -3023,21 +3051,21 @@
         }
     }
 
-    private boolean setLockCredentialWithToken(byte[] credential, int type, long tokenHandle,
-            byte[] token, int requestedQuality, int userId) {
+    private boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle,
+            byte[] token, int userId) {
         boolean result;
         synchronized (mSpManager) {
             if (!mSpManager.hasEscrowData(userId)) {
                 throw new SecurityException("Escrow token is disabled on the current user");
             }
-            result = setLockCredentialWithTokenInternalLocked(credential, type, tokenHandle, token,
-                    requestedQuality, userId);
+            result = setLockCredentialWithTokenInternalLocked(
+                    credential, tokenHandle, token, userId);
         }
         if (result) {
             synchronized (mSeparateChallengeLock) {
-                setSeparateProfileChallengeEnabledLocked(userId, true, null);
+                setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
             }
-            if (credential == null) {
+            if (credential.isNone()) {
                 // If clearing credential, unlock the user manually in order to progress user start
                 // Call unlockUser() on a handler thread so no lock is held (either by LSS or by
                 // the caller like DPMS), otherwise it can lead to deadlock.
@@ -3050,8 +3078,8 @@
     }
 
     @GuardedBy("mSpManager")
-    private boolean setLockCredentialWithTokenInternalLocked(byte[] credential, int type,
-            long tokenHandle, byte[] token, int requestedQuality, int userId) {
+    private boolean setLockCredentialWithTokenInternalLocked(LockscreenCredential credential,
+            long tokenHandle, byte[] token, int userId) {
         final AuthenticationResult result;
         result = mSpManager.unwrapTokenBasedSyntheticPassword(
                 getGateKeeperService(), tokenHandle, token, userId);
@@ -3066,11 +3094,8 @@
                     + "verification.");
             return false;
         }
-        // TODO: refactor usage of PASSWORD_TYPE_KEY b/65239740
-        setLong(LockPatternUtils.PASSWORD_TYPE_KEY, requestedQuality, userId);
         long oldHandle = getSyntheticPasswordHandleLocked(userId);
-        setLockCredentialWithAuthTokenLocked(credential, type, result.authToken,
-                requestedQuality, userId);
+        setLockCredentialWithAuthTokenLocked(credential, result.authToken, userId);
         mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
 
         onAuthTokenKnownForUser(userId, result.authToken);
@@ -3132,11 +3157,10 @@
             }
             // It's OK to dump the password type since anyone with physical access can just
             // observe it from the keyguard directly.
-            pw.println("PasswordType: " + getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 0, userId));
-            pw.println("hasPassword: " + havePassword(userId));
-            pw.println("hasPattern: " + havePattern(userId)); // print raw credential type instead?
+            pw.println("Quality: " + getKeyguardStoredQuality(userId));
+            pw.println("CredentialType: " + getCredentialTypeInternal(userId));
             pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabled(userId));
-            pw.println(String.format("metrics: %s",
+            pw.println(String.format("Metrics: %s",
                     getUserPasswordMetrics(userId) != null ? "known" : "unknown"));
             pw.decreaseIndent();
         }
@@ -3298,14 +3322,14 @@
         }
 
         @Override
-        public boolean setLockCredentialWithToken(byte[] credential, int type,
-                long tokenHandle, byte[] token, int requestedQuality, int userId) {
+        public boolean setLockCredentialWithToken(LockscreenCredential credential, long tokenHandle,
+                byte[] token, int userId) {
             if (!mLockPatternUtils.hasSecureLockScreen()) {
                 throw new UnsupportedOperationException(
                         "This operation requires secure lock screen feature.");
             }
-            return LockSettingsService.this.setLockCredentialWithToken(credential, type,
-                    tokenHandle, token, requestedQuality, userId);
+            return LockSettingsService.this.setLockCredentialWithToken(
+                    credential, tokenHandle, token, userId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
index 0a8e5bd..0f8561e 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java
@@ -16,14 +16,22 @@
 
 package com.android.server.locksettings;
 
+import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
+
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+
 import android.app.ActivityManager;
+import android.app.admin.PasswordMetrics;
 import android.os.ShellCommand;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
 import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.PasswordValidationError;
 
 import java.io.PrintWriter;
+import java.util.List;
 
 class LockSettingsShellCommand extends ShellCommand {
 
@@ -70,18 +78,19 @@
             if (!checkCredential()) {
                 return -1;
             }
+            boolean success = true;
             switch (cmd) {
                 case COMMAND_SET_PATTERN:
-                    runSetPattern();
+                    success = runSetPattern();
                     break;
                 case COMMAND_SET_PASSWORD:
-                    runSetPassword();
+                    success = runSetPassword();
                     break;
                 case COMMAND_SET_PIN:
-                    runSetPin();
+                    success = runSetPin();
                     break;
                 case COMMAND_CLEAR:
-                    runClear();
+                    success = runClear();
                     break;
                 case COMMAND_SP:
                     runChangeSp();
@@ -102,7 +111,7 @@
                     getErrPrintWriter().println("Unknown command: " + cmd);
                     break;
             }
-            return 0;
+            return success ? 0 : -1;
         } catch (Exception e) {
             getErrPrintWriter().println("Error while executing command: " + cmd);
             e.printStackTrace(getErrPrintWriter());
@@ -201,34 +210,66 @@
         }
     }
 
-    private void runSetPattern() {
-        mLockPatternUtils.setLockCredential(
-                LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(
-                        mNew.getBytes())),
-                getOldCredential(),
-                mCurrentUserId);
+    private boolean runSetPattern() {
+        final LockscreenCredential pattern = LockscreenCredential.createPattern(
+                LockPatternUtils.byteArrayToPattern(mNew.getBytes()));
+        if (!isNewCredentialSufficient(pattern)) {
+            return false;
+        }
+        mLockPatternUtils.setLockCredential(pattern, getOldCredential(), mCurrentUserId);
         getOutPrintWriter().println("Pattern set to '" + mNew + "'");
+        return true;
     }
 
-    private void runSetPassword() {
-        mLockPatternUtils.setLockCredential(LockscreenCredential.createPassword(mNew),
-                getOldCredential(),
-                mCurrentUserId);
+    private boolean runSetPassword() {
+        final LockscreenCredential password = LockscreenCredential.createPassword(mNew);
+        if (!isNewCredentialSufficient(password)) {
+            return false;
+        }
+        mLockPatternUtils.setLockCredential(password, getOldCredential(), mCurrentUserId);
         getOutPrintWriter().println("Password set to '" + mNew + "'");
+        return true;
     }
 
-    private void runSetPin() {
-        mLockPatternUtils.setLockCredential(LockscreenCredential.createPin(mNew),
-                getOldCredential(),
-                mCurrentUserId);
+    private boolean runSetPin() {
+        final LockscreenCredential pin = LockscreenCredential.createPin(mNew);
+        if (!isNewCredentialSufficient(pin)) {
+            return false;
+        }
+        mLockPatternUtils.setLockCredential(pin, getOldCredential(), mCurrentUserId);
         getOutPrintWriter().println("Pin set to '" + mNew + "'");
+        return true;
     }
 
-    private void runClear() {
-        mLockPatternUtils.setLockCredential(LockscreenCredential.createNone(),
-                getOldCredential(),
-                mCurrentUserId);
+    private boolean runClear() {
+        LockscreenCredential none = LockscreenCredential.createNone();
+        if (!isNewCredentialSufficient(none)) {
+            return false;
+        }
+        mLockPatternUtils.setLockCredential(none, getOldCredential(), mCurrentUserId);
         getOutPrintWriter().println("Lock credential cleared");
+        return true;
+    }
+
+    private boolean isNewCredentialSufficient(LockscreenCredential credential) {
+        final PasswordMetrics requiredMetrics =
+                mLockPatternUtils.getRequestedPasswordMetrics(mCurrentUserId);
+        final List<PasswordValidationError> errors;
+        if (credential.isPassword() || credential.isPin()) {
+            errors = PasswordMetrics.validatePassword(requiredMetrics, PASSWORD_COMPLEXITY_NONE,
+                    credential.isPin(), credential.getCredential());
+        } else {
+            PasswordMetrics metrics = new PasswordMetrics(
+                    credential.isPattern() ? CREDENTIAL_TYPE_PATTERN : CREDENTIAL_TYPE_NONE);
+            errors = PasswordMetrics.validatePasswordMetrics(
+                    requiredMetrics, PASSWORD_COMPLEXITY_NONE, false /* isPin */, metrics);
+        }
+        if (!errors.isEmpty()) {
+            getOutPrintWriter().println(
+                    "New credential doesn't satisfy admin policies: " + errors.get(0));
+            return false;
+        }
+        return true;
     }
 
     private void runSetDisabled() {
@@ -243,9 +284,7 @@
     }
 
     private boolean checkCredential() {
-        final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
-        final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
-        if (havePassword || havePattern) {
+        if (mLockPatternUtils.isSecure(mCurrentUserId)) {
             if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(mCurrentUserId)) {
                 getOutPrintWriter().println("Profile uses unified challenge");
                 return false;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index f4cad63..3dab3ce 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -30,7 +30,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -214,7 +213,7 @@
     private CredentialHash readPasswordHashIfExists(int userId) {
         byte[] stored = readFile(getLockPasswordFilename(userId));
         if (!ArrayUtils.isEmpty(stored)) {
-            return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
+            return new CredentialHash(stored, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN);
         }
         return null;
     }
@@ -270,10 +269,6 @@
         return hasFile(getLockPatternFilename(userId));
     }
 
-    public boolean hasCredential(int userId) {
-        return hasPassword(userId) || hasPattern(userId);
-    }
-
     private boolean hasFile(String name) {
         byte[] contents = readFile(name);
         return contents != null && contents.length > 0;
@@ -360,11 +355,15 @@
     public void writeCredentialHash(CredentialHash hash, int userId) {
         byte[] patternHash = null;
         byte[] passwordHash = null;
-
-        if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
+        if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN
+                || hash.type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
+                || hash.type == LockPatternUtils.CREDENTIAL_TYPE_PIN) {
             passwordHash = hash.hash;
         } else if (hash.type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
             patternHash = hash.hash;
+        } else {
+            Preconditions.checkArgument(hash.type == LockPatternUtils.CREDENTIAL_TYPE_NONE,
+                    "Unknown credential type");
         }
         writeFile(getLockPasswordFilename(userId), passwordHash);
         writeFile(getLockPatternFilename(userId), patternHash);
@@ -523,8 +522,8 @@
         mCache.clear();
     }
 
-    @Nullable
-    public PersistentDataBlockManagerInternal getPersistentDataBlock() {
+    @Nullable @VisibleForTesting
+    PersistentDataBlockManagerInternal getPersistentDataBlockManager() {
         if (mPersistentDataBlockManagerInternal == null) {
             mPersistentDataBlockManagerInternal =
                     LocalServices.getService(PersistentDataBlockManagerInternal.class);
@@ -534,7 +533,7 @@
 
     public void writePersistentDataBlock(int persistentType, int userId, int qualityForUi,
             byte[] payload) {
-        PersistentDataBlockManagerInternal persistentDataBlock = getPersistentDataBlock();
+        PersistentDataBlockManagerInternal persistentDataBlock = getPersistentDataBlockManager();
         if (persistentDataBlock == null) {
             return;
         }
@@ -543,7 +542,7 @@
     }
 
     public PersistentData readPersistentDataBlock() {
-        PersistentDataBlockManagerInternal persistentDataBlock = getPersistentDataBlock();
+        PersistentDataBlockManagerInternal persistentDataBlock = getPersistentDataBlockManager();
         if (persistentDataBlock == null) {
             return PersistentData.NONE;
         }
@@ -699,7 +698,7 @@
             }
 
             if (upgradeVersion != DATABASE_VERSION) {
-                Log.w(TAG, "Failed to upgrade database!");
+                Slog.w(TAG, "Failed to upgrade database!");
             }
         }
     }
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 955a9aa..53d922b 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -20,7 +20,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.hardware.weaver.V1_0.IWeaver;
@@ -35,13 +34,13 @@
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.ICheckCredentialProgressCallback;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.locksettings.LockSettingsStorage.PersistentData;
 
@@ -138,7 +137,6 @@
     static class AuthenticationResult {
         public AuthenticationToken authToken;
         public VerifyCredentialResponse gkResponse;
-        public int credentialType;
     }
 
     static class AuthenticationToken {
@@ -220,7 +218,7 @@
         byte scryptN;
         byte scryptR;
         byte scryptP;
-        public int passwordType;
+        public int credentialType;
         byte[] salt;
         // For GateKeeper-based credential, this is the password handle returned by GK,
         // for weaver-based credential, this is empty.
@@ -231,7 +229,7 @@
             result.scryptN = PASSWORD_SCRYPT_N;
             result.scryptR = PASSWORD_SCRYPT_R;
             result.scryptP = PASSWORD_SCRYPT_P;
-            result.passwordType = passwordType;
+            result.credentialType = passwordType;
             result.salt = secureRandom(PASSWORD_SALT_LENGTH);
             return result;
         }
@@ -241,7 +239,7 @@
             ByteBuffer buffer = ByteBuffer.allocate(data.length);
             buffer.put(data, 0, data.length);
             buffer.flip();
-            result.passwordType = buffer.getInt();
+            result.credentialType = buffer.getInt();
             result.scryptN = buffer.get();
             result.scryptR = buffer.get();
             result.scryptP = buffer.get();
@@ -263,7 +261,7 @@
             ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES + 3 * Byte.BYTES
                     + Integer.BYTES + salt.length + Integer.BYTES +
                     (passwordHandle != null ? passwordHandle.length : 0));
-            buffer.putInt(passwordType);
+            buffer.putInt(credentialType);
             buffer.put(scryptN);
             buffer.put(scryptR);
             buffer.put(scryptP);
@@ -366,11 +364,11 @@
         try {
             int writeStatus = mWeaver.write(slot, toByteArrayList(key), toByteArrayList(value));
             if (writeStatus != WeaverStatus.OK) {
-                Log.e(TAG, "weaver write failed, slot: " + slot + " status: " + writeStatus);
+                Slog.e(TAG, "weaver write failed, slot: " + slot + " status: " + writeStatus);
                 return null;
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "weaver write failed", e);
+            Slog.e(TAG, "weaver write failed", e);
             return null;
         }
         return value;
@@ -401,31 +399,31 @@
                             break;
                         case WeaverReadStatus.THROTTLE:
                             response[0] = new VerifyCredentialResponse(readResponse.timeout);
-                            Log.e(TAG, "weaver read failed (THROTTLE), slot: " + slot);
+                            Slog.e(TAG, "weaver read failed (THROTTLE), slot: " + slot);
                             break;
                         case WeaverReadStatus.INCORRECT_KEY:
                             if (readResponse.timeout == 0) {
                                 response[0] = VerifyCredentialResponse.ERROR;
-                                Log.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot);
+                                Slog.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot);
                             } else {
                                 response[0] = new VerifyCredentialResponse(readResponse.timeout);
-                                Log.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: "
+                                Slog.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: "
                                         + slot);
                             }
                             break;
                         case WeaverReadStatus.FAILED:
                             response[0] = VerifyCredentialResponse.ERROR;
-                            Log.e(TAG, "weaver read failed (FAILED), slot: " + slot);
+                            Slog.e(TAG, "weaver read failed (FAILED), slot: " + slot);
                             break;
                         default:
                             response[0] = VerifyCredentialResponse.ERROR;
-                            Log.e(TAG, "weaver read unknown status " + status + ", slot: " + slot);
+                            Slog.e(TAG, "weaver read unknown status " + status + ", slot: " + slot);
                             break;
                     }
                 });
         } catch (RemoteException e) {
             response[0] = VerifyCredentialResponse.ERROR;
-            Log.e(TAG, "weaver read failed, slot: " + slot, e);
+            Slog.e(TAG, "weaver read failed, slot: " + slot, e);
         }
         return response[0];
     }
@@ -437,13 +435,20 @@
         }
     }
 
-    public int getCredentialType(long handle, int userId) {
+    int getCredentialType(long handle, int userId) {
         byte[] passwordData = loadState(PASSWORD_DATA_NAME, handle, userId);
         if (passwordData == null) {
-            Log.w(TAG, "getCredentialType: encountered empty password data for user " + userId);
+            Slog.w(TAG, "getCredentialType: encountered empty password data for user " + userId);
             return LockPatternUtils.CREDENTIAL_TYPE_NONE;
         }
-        return PasswordData.fromBytes(passwordData).passwordType;
+        return PasswordData.fromBytes(passwordData).credentialType;
+    }
+
+    static int getFrpCredentialType(byte[] payload) {
+        if (payload == null) {
+            return LockPatternUtils.CREDENTIAL_TYPE_NONE;
+        }
+        return PasswordData.fromBytes(payload).credentialType;
     }
 
     /**
@@ -469,17 +474,18 @@
      *
      */
     public AuthenticationToken newSyntheticPasswordAndSid(IGateKeeperService gatekeeper,
-            byte[] hash, byte[] credential, int userId) {
+            byte[] hash, LockscreenCredential credential, int userId) {
         AuthenticationToken result = AuthenticationToken.create();
         GateKeeperResponse response;
         if (hash != null) {
             try {
-                response = gatekeeper.enroll(userId, hash, credential, result.deriveGkPassword());
+                response = gatekeeper.enroll(userId, hash, credential.getCredential(),
+                        result.deriveGkPassword());
             } catch (RemoteException e) {
                 throw new IllegalStateException("Failed to enroll credential duing SP init", e);
             }
             if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
-                Log.w(TAG, "Fail to migrate SID, assuming no SID, user " + userId);
+                Slog.w(TAG, "Fail to migrate SID, assuming no SID, user " + userId);
                 clearSidForUser(userId);
             } else {
                 saveSyntheticPasswordHandle(response.getPayload(), userId);
@@ -504,7 +510,7 @@
             throw new IllegalStateException("Failed to create new SID for user", e);
         }
         if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
-            Log.e(TAG, "Fail to create new SID for user " + userId);
+            Slog.e(TAG, "Fail to create new SID for user " + userId);
             return;
         }
         saveSyntheticPasswordHandle(response.getPayload(), userId);
@@ -561,7 +567,7 @@
         buffer.put(data, 0, data.length);
         buffer.flip();
         if (buffer.get() != WEAVER_VERSION) {
-            Log.e(TAG, "Invalid weaver slot version of handle " + handle);
+            Slog.e(TAG, "Invalid weaver slot version of handle " + handle);
             return INVALID_WEAVER_SLOT;
         }
         return buffer.getInt();
@@ -580,11 +586,11 @@
         if (slot != INVALID_WEAVER_SLOT) {
             Set<Integer> usedSlots = getUsedWeaverSlots();
             if (!usedSlots.contains(slot)) {
-                Log.i(TAG, "Destroy weaver slot " + slot + " for user " + userId);
+                Slog.i(TAG, "Destroy weaver slot " + slot + " for user " + userId);
                 weaverEnroll(slot, null, null);
                 mPasswordSlotManager.markSlotDeleted(slot);
             } else {
-                Log.w(TAG, "Skip destroying reused weaver slot " + slot + " for user " + userId);
+                Slog.w(TAG, "Skip destroying reused weaver slot " + slot + " for user " + userId);
             }
         }
     }
@@ -638,15 +644,9 @@
      * @throw IllegalStateException if creation fails.
      */
     public long createPasswordBasedSyntheticPassword(IGateKeeperService gatekeeper,
-            byte[] credential, int credentialType, AuthenticationToken authToken,
-            int requestedQuality, int userId) {
-        if (credential == null || credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
-            credentialType = LockPatternUtils.CREDENTIAL_TYPE_NONE;
-            credential = DEFAULT_PASSWORD;
-        }
-
+            LockscreenCredential credential, AuthenticationToken authToken, int userId) {
         long handle = generateHandle();
-        PasswordData pwd = PasswordData.create(credentialType);
+        PasswordData pwd = PasswordData.create(credential.getType());
         byte[] pwdToken = computePasswordToken(credential, pwd);
         final long sid;
         final byte[] applicationId;
@@ -654,7 +654,7 @@
         if (isWeaverAvailable()) {
             // Weaver based user password
             int weaverSlot = getNextAvailableWeaverSlot();
-            Log.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
+            Slog.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
             byte[] weaverSecret = weaverEnroll(weaverSlot, passwordTokenToWeaverKey(pwdToken),
                     null);
             if (weaverSecret == null) {
@@ -663,7 +663,8 @@
             }
             saveWeaverSlot(weaverSlot, handle, userId);
             mPasswordSlotManager.markSlotInUse(weaverSlot);
-            synchronizeWeaverFrpPassword(pwd, requestedQuality, userId, weaverSlot);
+            // No need to pass in quality since the credential type already encodes sufficient info
+            synchronizeWeaverFrpPassword(pwd, 0, userId, weaverSlot);
 
             pwd.passwordHandle = null;
             sid = GateKeeper.INVALID_SECURE_USER_ID;
@@ -674,7 +675,7 @@
             try {
                 gatekeeper.clearSecureUserId(fakeUid(userId));
             } catch (RemoteException ignore) {
-                Log.w(TAG, "Failed to clear SID from gatekeeper");
+                Slog.w(TAG, "Failed to clear SID from gatekeeper");
             }
             // GateKeeper based user password
             GateKeeperResponse response;
@@ -692,7 +693,8 @@
             sid = sidFromPasswordHandle(pwd.passwordHandle);
             applicationId = transformUnderSecdiscardable(pwdToken,
                     createSecdiscardable(handle, userId));
-            synchronizeFrpPassword(pwd, requestedQuality, userId);
+            // No need to pass in quality since the credential type already encodes sufficient info
+            synchronizeFrpPassword(pwd, 0, userId);
         }
         saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);
 
@@ -702,7 +704,7 @@
     }
 
     public VerifyCredentialResponse verifyFrpCredential(IGateKeeperService gatekeeper,
-            byte[] userCredential, int credentialType,
+            LockscreenCredential userCredential,
             ICheckCredentialProgressCallback progressCallback) {
         PersistentData persistentData = mStorage.readPersistentDataBlock();
         if (persistentData.type == PersistentData.TYPE_SP) {
@@ -714,7 +716,7 @@
                 response = gatekeeper.verifyChallenge(fakeUid(persistentData.userId),
                         0 /* challenge */, pwd.passwordHandle, passwordTokenToGkInput(pwdToken));
             } catch (RemoteException e) {
-                Log.e(TAG, "FRP verifyChallenge failed", e);
+                Slog.e(TAG, "FRP verifyChallenge failed", e);
                 return VerifyCredentialResponse.ERROR;
             }
             return VerifyCredentialResponse.fromGateKeeperResponse(response);
@@ -725,7 +727,7 @@
 
             return weaverVerify(weaverSlot, passwordTokenToWeaverKey(pwdToken)).stripPayload();
         } else {
-            Log.e(TAG, "persistentData.type must be TYPE_SP or TYPE_SP_WEAVER, but is "
+            Slog.e(TAG, "persistentData.type must be TYPE_SP or TYPE_SP_WEAVER, but is "
                     + persistentData.type);
             return VerifyCredentialResponse.ERROR;
         }
@@ -733,11 +735,11 @@
 
 
     public void migrateFrpPasswordLocked(long handle, UserInfo userInfo, int requestedQuality) {
-        if (mStorage.getPersistentDataBlock() != null
+        if (mStorage.getPersistentDataBlockManager() != null
                 && LockPatternUtils.userOwnsFrpCredential(mContext, userInfo)) {
             PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, handle,
                     userInfo.id));
-            if (pwd.passwordType != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+            if (pwd.credentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
                 int weaverSlot = loadWeaverSlot(handle, userInfo.id);
                 if (weaverSlot != INVALID_WEAVER_SLOT) {
                     synchronizeWeaverFrpPassword(pwd, requestedQuality, userInfo.id, weaverSlot);
@@ -750,10 +752,10 @@
 
     private void synchronizeFrpPassword(PasswordData pwd,
             int requestedQuality, int userId) {
-        if (mStorage.getPersistentDataBlock() != null
+        if (mStorage.getPersistentDataBlockManager() != null
                 && LockPatternUtils.userOwnsFrpCredential(mContext,
                 mUserManager.getUserInfo(userId))) {
-            if (pwd.passwordType != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+            if (pwd.credentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
                 mStorage.writePersistentDataBlock(PersistentData.TYPE_SP, userId, requestedQuality,
                         pwd.toBytes());
             } else {
@@ -764,10 +766,10 @@
 
     private void synchronizeWeaverFrpPassword(PasswordData pwd, int requestedQuality, int userId,
             int weaverSlot) {
-        if (mStorage.getPersistentDataBlock() != null
+        if (mStorage.getPersistentDataBlockManager() != null
                 && LockPatternUtils.userOwnsFrpCredential(mContext,
                 mUserManager.getUserInfo(userId))) {
-            if (pwd.passwordType != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
+            if (pwd.credentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE) {
                 mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_WEAVER, weaverSlot,
                         requestedQuality, pwd.toBytes());
             } else {
@@ -829,14 +831,14 @@
             return false;
         }
         if (!loadEscrowData(authToken, userId)) {
-            Log.w(TAG, "User is not escrowable");
+            Slog.w(TAG, "User is not escrowable");
             return false;
         }
         if (isWeaverAvailable()) {
             int slot = getNextAvailableWeaverSlot();
-            Log.i(TAG, "Weaver enroll token to slot " + slot + " for user " + userId);
+            Slog.i(TAG, "Weaver enroll token to slot " + slot + " for user " + userId);
             if (weaverEnroll(slot, null, tokenData.weaverSecret) == null) {
-                Log.e(TAG, "Failed to enroll weaver secret when activating token");
+                Slog.e(TAG, "Failed to enroll weaver secret when activating token");
                 return false;
             }
             saveWeaverSlot(slot, handle, userId);
@@ -881,18 +883,20 @@
      * Decrypt a synthetic password by supplying the user credential and corresponding password
      * blob handle generated previously. If the decryption is successful, initiate a GateKeeper
      * verification to referesh the SID & Auth token maintained by the system.
-     * Note: the credential type is not validated here since there are call sites where the type is
-     * unknown. Caller might choose to validate it by examining AuthenticationResult.credentialType
      */
     public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperService gatekeeper,
-            long handle, byte[] credential, int userId,
+            long handle, @NonNull LockscreenCredential credential, int userId,
             ICheckCredentialProgressCallback progressCallback) {
-        if (credential == null) {
-            credential = DEFAULT_PASSWORD;
-        }
         AuthenticationResult result = new AuthenticationResult();
         PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, handle, userId));
-        result.credentialType = pwd.passwordType;
+
+        if (!credential.checkAgainstStoredType(pwd.credentialType)) {
+            Slog.e(TAG, String.format("Credential type mismatch: expected %d actual %d",
+                    pwd.credentialType, credential.getType()));
+            result.gkResponse = VerifyCredentialResponse.ERROR;
+            return result;
+        }
+
         byte[] pwdToken = computePasswordToken(credential, pwd);
 
         final byte[] applicationId;
@@ -901,7 +905,7 @@
         if (weaverSlot != INVALID_WEAVER_SLOT) {
             // Weaver based user password
             if (!isWeaverAvailable()) {
-                Log.e(TAG, "No weaver service to unwrap password based SP");
+                Slog.e(TAG, "No weaver service to unwrap password based SP");
                 result.gkResponse = VerifyCredentialResponse.ERROR;
                 return result;
             }
@@ -918,7 +922,7 @@
                 response = gatekeeper.verifyChallenge(fakeUid(userId), 0L,
                         pwd.passwordHandle, gkPwdToken);
             } catch (RemoteException e) {
-                Log.e(TAG, "gatekeeper verify failed", e);
+                Slog.e(TAG, "gatekeeper verify failed", e);
                 result.gkResponse = VerifyCredentialResponse.ERROR;
                 return result;
             }
@@ -931,21 +935,19 @@
                         reenrollResponse = gatekeeper.enroll(fakeUid(userId),
                                 pwd.passwordHandle, gkPwdToken, gkPwdToken);
                     } catch (RemoteException e) {
-                        Log.w(TAG, "Fail to invoke gatekeeper.enroll", e);
+                        Slog.w(TAG, "Fail to invoke gatekeeper.enroll", e);
                         reenrollResponse = GateKeeperResponse.ERROR;
                         // continue the flow anyway
                     }
                     if (reenrollResponse.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
                         pwd.passwordHandle = reenrollResponse.getPayload();
+                        // Use the reenrollment opportunity to update credential type
+                        // (getting rid of CREDENTIAL_TYPE_PASSWORD_OR_PIN)
+                        pwd.credentialType = credential.getType();
                         saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);
-                        synchronizeFrpPassword(pwd,
-                                pwd.passwordType == LockPatternUtils.CREDENTIAL_TYPE_PATTERN
-                                ? DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
-                                : DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
-                                /* TODO(roosa): keep the same password quality */,
-                                userId);
+                        synchronizeFrpPassword(pwd, 0, userId);
                     } else {
-                        Log.w(TAG, "Fail to re-enroll user password for user " + userId);
+                        Slog.w(TAG, "Fail to re-enroll user password for user " + userId);
                         // continue the flow anyway
                     }
                 }
@@ -966,7 +968,7 @@
             try {
                 progressCallback.onCredentialVerified();
             } catch (RemoteException e) {
-                Log.w(TAG, "progressCallback throws exception", e);
+                Slog.w(TAG, "progressCallback throws exception", e);
             }
         }
         result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED,
@@ -989,14 +991,14 @@
         int slotId = loadWeaverSlot(handle, userId);
         if (slotId != INVALID_WEAVER_SLOT) {
             if (!isWeaverAvailable()) {
-                Log.e(TAG, "No weaver service to unwrap token based SP");
+                Slog.e(TAG, "No weaver service to unwrap token based SP");
                 result.gkResponse = VerifyCredentialResponse.ERROR;
                 return result;
             }
             VerifyCredentialResponse response = weaverVerify(slotId, null);
             if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK ||
                     response.getPayload() == null) {
-                Log.e(TAG, "Failed to retrieve weaver secret when unwrapping token");
+                Slog.e(TAG, "Failed to retrieve weaver secret when unwrapping token");
                 result.gkResponse = VerifyCredentialResponse.ERROR;
                 return result;
             }
@@ -1043,13 +1045,13 @@
                 Arrays.copyOfRange(blob, 2, blob.length), applicationId);
         }
         if (secret == null) {
-            Log.e(TAG, "Fail to decrypt SP for user " + userId);
+            Slog.e(TAG, "Fail to decrypt SP for user " + userId);
             return null;
         }
         AuthenticationToken result = new AuthenticationToken(version);
         if (type == SYNTHETIC_PASSWORD_TOKEN_BASED) {
             if (!loadEscrowData(result, userId)) {
-                Log.e(TAG, "User is not escrowable: " + userId);
+                Slog.e(TAG, "User is not escrowable: " + userId);
                 return null;
             }
             result.recreate(secret);
@@ -1057,7 +1059,7 @@
             result.syntheticPassword = new String(secret);
         }
         if (version == SYNTHETIC_PASSWORD_VERSION_V1) {
-            Log.i(TAG, "Upgrade v1 SP blob for user " + userId + ", type = " + type);
+            Slog.i(TAG, "Upgrade v1 SP blob for user " + userId + ", type = " + type);
             createSyntheticPasswordBlob(handle, type, result, applicationId, sid, userId);
         }
         return result;
@@ -1084,7 +1086,7 @@
             response = gatekeeper.verifyChallenge(userId, challenge,
                     spHandle, auth.deriveGkPassword());
         } catch (RemoteException e) {
-            Log.e(TAG, "Fail to verify with gatekeeper " + userId, e);
+            Slog.e(TAG, "Fail to verify with gatekeeper " + userId, e);
             return VerifyCredentialResponse.ERROR;
         }
         int responseCode = response.getResponseCode();
@@ -1095,7 +1097,7 @@
                     response = gatekeeper.enroll(userId, spHandle, spHandle,
                             auth.deriveGkPassword());
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to invoke gatekeeper.enroll", e);
+                    Slog.e(TAG, "Failed to invoke gatekeeper.enroll", e);
                     response = GateKeeperResponse.ERROR;
                 }
                 if (response.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
@@ -1105,7 +1107,7 @@
                     return verifyChallenge(gatekeeper, auth, challenge, userId);
                 } else {
                     // Fall through, return result from the previous verification attempt.
-                    Log.w(TAG, "Fail to re-enroll SP handle for user " + userId);
+                    Slog.w(TAG, "Fail to re-enroll SP handle for user " + userId);
                 }
             }
             return result;
@@ -1225,7 +1227,8 @@
         return String.format("%s%x", LockPatternUtils.SYNTHETIC_PASSWORD_KEY_PREFIX, handle);
     }
 
-    private byte[] computePasswordToken(byte[] password, PasswordData data) {
+    private byte[] computePasswordToken(LockscreenCredential credential, PasswordData data) {
+        final byte[] password = credential.isNone() ? DEFAULT_PASSWORD : credential.getCredential();
         return scrypt(password, data.salt, 1 << data.scryptN, 1 << data.scryptR, 1 << data.scryptP,
                 PASSWORD_TOKEN_LENGTH);
     }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 5676da2..29338ba0 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -18,7 +18,6 @@
 
 import static android.security.keystore.recovery.KeyChainProtectionParams.TYPE_LOCKSCREEN;
 
-import android.annotation.Nullable;
 import android.content.Context;
 import android.os.RemoteException;
 import android.security.Scrypt;
@@ -193,6 +192,7 @@
     private boolean isCustomLockScreen() {
         return mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE
             && mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PATTERN
+            && mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PIN
             && mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
     }
 
@@ -345,7 +345,7 @@
         }
         KeyChainProtectionParams keyChainProtectionParams = new KeyChainProtectionParams.Builder()
                 .setUserSecretType(TYPE_LOCKSCREEN)
-                .setLockScreenUiFormat(getUiFormat(mCredentialType, mCredential))
+                .setLockScreenUiFormat(getUiFormat(mCredentialType))
                 .setKeyDerivationParams(keyDerivationParams)
                 .setSecret(new byte[0])
                 .build();
@@ -449,11 +449,10 @@
      * @return The format - either pattern, pin, or password.
      */
     @VisibleForTesting
-    @KeyChainProtectionParams.LockScreenUiFormat static int getUiFormat(
-            int credentialType, byte[] credential) {
+    @KeyChainProtectionParams.LockScreenUiFormat static int getUiFormat(int credentialType) {
         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
             return KeyChainProtectionParams.UI_FORMAT_PATTERN;
-        } else if (isPin(credential)) {
+        } else if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PIN) {
             return KeyChainProtectionParams.UI_FORMAT_PIN;
         } else {
             return KeyChainProtectionParams.UI_FORMAT_PASSWORD;
@@ -472,23 +471,6 @@
     }
 
     /**
-     * Returns {@code true} if {@code credential} looks like a pin.
-     */
-    @VisibleForTesting
-    static boolean isPin(@Nullable byte[] credential) {
-        if (credential == null) {
-            return false;
-        }
-        int length = credential.length;
-        for (int i = 0; i < length; i++) {
-            if (!Character.isDigit((char) credential[i])) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
      * Hashes {@code credentials} with the given {@code salt}.
      *
      * @return The SHA-256 hash.
@@ -541,6 +523,7 @@
     }
 
     private boolean shouldUseScryptToHashCredential() {
-        return mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+        return mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
+                || mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_PIN;
     }
 }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
index 90a36723..c963f79 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java
@@ -97,7 +97,8 @@
         if (credential == null) {
             return false;
         }
-        if (credentialType != LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
+        if (credentialType != LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
+                && credentialType != LockPatternUtils.CREDENTIAL_TYPE_PIN) {
             return false;
         }
         byte[] insecurePasswordPrefixBytes =
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index 9eac252..4816ceb 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -43,7 +43,7 @@
  * Maintains a connection to a particular media route provider service.
  */
 final class MediaRoute2ProviderProxy implements ServiceConnection {
-    private static final String TAG = "MediaRoute2Provider";
+    private static final String TAG = "MR2ProviderProxy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
@@ -274,7 +274,9 @@
                 .setUniqueId(mUniqueId)
                 .build();
         }
-        mHandler.post(mStateChanged);
+        if (mCallback != null) {
+            mCallback.onProviderStateChanged(MediaRoute2ProviderProxy.this);
+        }
     }
 
     private void disconnect() {
@@ -291,15 +293,6 @@
         return "Service connection " + mComponentName.flattenToShortString();
     }
 
-    private final Runnable mStateChanged = new Runnable() {
-        @Override
-        public void run() {
-            if (mCallback != null) {
-                mCallback.onProviderStateChanged(MediaRoute2ProviderProxy.this);
-            }
-        }
-    };
-
     public interface Callback {
         void onProviderStateChanged(MediaRoute2ProviderProxy provider);
     }
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
index 194015d..c95119d 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderWatcher.java
@@ -35,9 +35,10 @@
 import java.util.Collections;
 
 /**
+ * Watches changes of packages, or scan them for finding media route providers.
  */
 final class MediaRoute2ProviderWatcher {
-    private static final String TAG = "MediaRouteProvider";  // max. 23 chars
+    private static final String TAG = "MR2ProviderWatcher";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 74d59ac..361dc36 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -55,7 +55,7 @@
  * TODO: Merge this to MediaRouterService once it's finished.
  */
 class MediaRouter2ServiceImpl {
-    private static final String TAG = "MediaRouter2ServiceImpl";
+    private static final String TAG = "MR2ServiceImpl";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
@@ -339,11 +339,11 @@
             int uid, int pid, String packageName, int userId, boolean trusted) {
         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;
+                mUserRecords.put(userId, userRecord);
+                initializeUserLocked(userRecord);
             }
             Client2Record clientRecord = new Client2Record(userRecord, client, uid, pid,
                     packageName, trusted);
@@ -353,11 +353,6 @@
                 throw new RuntimeException("Media router client died prematurely.", ex);
             }
 
-            if (newUser) {
-                mUserRecords.put(userId, userRecord);
-                initializeUserLocked(userRecord);
-            }
-
             userRecord.mClientRecords.add(clientRecord);
             mAllClientRecords.put(binder, clientRecord);
 
@@ -815,8 +810,6 @@
             if (service == null) {
                 return;
             }
-            final List<IMediaRouter2Manager> managers = new ArrayList<>();
-            final List<IMediaRouter2Client> clients = new ArrayList<>();
             final List<MediaRoute2ProviderInfo> providers = new ArrayList<>();
             for (MediaRoute2ProviderProxy mediaProvider : mMediaProviders) {
                 final MediaRoute2ProviderInfo providerInfo =
@@ -829,6 +822,8 @@
             }
             mProviderInfos = providers;
 
+            final List<IMediaRouter2Manager> managers = new ArrayList<>();
+            final List<IMediaRouter2Client> clients = new ArrayList<>();
             synchronized (service.mLock) {
                 for (ManagerRecord managerRecord : mUserRecord.mManagerRecords) {
                     managers.add(managerRecord.mManager);
@@ -878,9 +873,8 @@
             }
             List<IMediaRouter2Manager> managers = new ArrayList<>();
             synchronized (service.mLock) {
-                final int count = mUserRecord.mManagerRecords.size();
-                for (int i = 0; i < count; i++) {
-                    managers.add(mUserRecord.mManagerRecords.get(i).mManager);
+                for (ManagerRecord managerRecord : mUserRecord.mManagerRecords) {
+                    managers.add(managerRecord.mManager);
                 }
             }
             for (IMediaRouter2Manager manager : managers) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 812ce32..3b14d50 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -229,6 +229,8 @@
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
+import com.android.server.usage.AppStandbyInternal;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import libcore.io.IoUtils;
 
@@ -396,6 +398,7 @@
     private NetworkStatsManagerInternal mNetworkStats;
     private final INetworkManagementService mNetworkManager;
     private UsageStatsManagerInternal mUsageStats;
+    private AppStandbyInternal mAppStandby;
     private final Clock mClock;
     private final UserManager mUserManager;
     private final CarrierConfigManager mCarrierConfigManager;
@@ -734,6 +737,7 @@
             }
 
             mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
+            mAppStandby = LocalServices.getService(AppStandbyInternal.class);
             mNetworkStats = LocalServices.getService(NetworkStatsManagerInternal.class);
 
             synchronized (mUidRulesFirstLock) {
@@ -797,6 +801,7 @@
                         writePolicyAL();
                     }
 
+                    enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, true);
                     setRestrictBackgroundUL(mLoadedRestrictBackground);
                     updateRulesForGlobalChangeAL(false);
                     updateNotificationsNL();
@@ -867,7 +872,7 @@
             mContext.getSystemService(ConnectivityManager.class).registerNetworkCallback(
                     new NetworkRequest.Builder().build(), mNetworkCallback);
 
-            mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
+            mAppStandby.addListener(new NetPolicyAppIdleStateChangeListener());
 
             // Listen for subscriber changes
             mContext.getSystemService(SubscriptionManager.class).addOnSubscriptionsChangedListener(
@@ -3830,39 +3835,6 @@
     }
 
     /**
-     * Toggle the firewall standby chain and inform listeners if the uid rules have effectively
-     * changed.
-     */
-    @GuardedBy("mUidRulesFirstLock")
-    void updateRulesForAppIdleParoleUL() {
-        boolean paroled = mUsageStats.isAppIdleParoleOn();
-        boolean enableChain = !paroled;
-        enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, enableChain);
-
-        int ruleCount = mUidFirewallStandbyRules.size();
-        for (int i = 0; i < ruleCount; i++) {
-            int uid = mUidFirewallStandbyRules.keyAt(i);
-            int oldRules = mUidRules.get(uid);
-            if (enableChain) {
-                // Chain wasn't enabled before and the other power-related
-                // chains are whitelists, so we can clear the
-                // MASK_ALL_NETWORKS part of the rules and re-inform listeners if
-                // the effective rules result in blocking network access.
-                oldRules &= MASK_METERED_NETWORKS;
-            } else {
-                // Skip if it had no restrictions to begin with
-                if ((oldRules & MASK_ALL_NETWORKS) == 0) continue;
-            }
-            final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldRules, paroled);
-            if (newUidRules == RULE_NONE) {
-                mUidRules.delete(uid);
-            } else {
-                mUidRules.put(uid, newUidRules);
-            }
-        }
-    }
-
-    /**
      * Update rules that might be changed by {@link #mRestrictBackground},
      * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
      */
@@ -4317,7 +4289,7 @@
     private void updateRulesForPowerRestrictionsUL(int uid) {
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
 
-        final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules, false);
+        final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldUidRules);
 
         if (newUidRules == RULE_NONE) {
             mUidRules.delete(uid);
@@ -4331,30 +4303,28 @@
      *
      * @param uid the uid of the app to update rules for
      * @param oldUidRules the current rules for the uid, in order to determine if there's a change
-     * @param paroled whether to ignore idle state of apps and only look at other restrictions.
      *
      * @return the new computed rules for the uid
      */
-    private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules, boolean paroled) {
+    private int updateRulesForPowerRestrictionsUL(int uid, int oldUidRules) {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
-                    "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules + "/"
-                    + (paroled ? "P" : "-"));
+                    "updateRulesForPowerRestrictionsUL: " + uid + "/" + oldUidRules);
         }
         try {
-            return updateRulesForPowerRestrictionsULInner(uid, oldUidRules, paroled);
+            return updateRulesForPowerRestrictionsULInner(uid, oldUidRules);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
         }
     }
 
-    private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules, boolean paroled) {
+    private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules) {
         if (!isUidValidForBlacklistRules(uid)) {
             if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
             return RULE_NONE;
         }
 
-        final boolean isIdle = !paroled && isUidIdle(uid);
+        final boolean isIdle = isUidIdle(uid);
         final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
         final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
 
@@ -4409,9 +4379,7 @@
         return newUidRules;
     }
 
-    private class AppIdleStateChangeListener
-            extends UsageStatsManagerInternal.AppIdleStateChangeListener {
-
+    private class NetPolicyAppIdleStateChangeListener extends AppIdleStateChangeListener {
         @Override
         public void onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket,
                 int reason) {
@@ -4426,14 +4394,6 @@
             } catch (NameNotFoundException nnfe) {
             }
         }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            synchronized (mUidRulesFirstLock) {
-                mLogger.paroleStateChanged(isParoleOn);
-                updateRulesForAppIdleParoleUL();
-            }
-        }
     }
 
     private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) {
@@ -4775,7 +4735,7 @@
     }
 
     /**
-     * Calls {@link #setUidFirewallRules(int, SparseIntArray)} and
+     * Calls {@link #setUidFirewallRulesUL(int, SparseIntArray)} and
      * {@link #enableFirewallChainUL(int, boolean)} synchronously.
      *
      * @param chain firewall chain.
diff --git a/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java b/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java
new file mode 100644
index 0000000..65a4b23
--- /dev/null
+++ b/services/core/java/com/android/server/net/watchlist/HarmfulCrcs.java
@@ -0,0 +1,63 @@
+/*
+ * 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.server.net.watchlist;
+
+import com.android.internal.util.HexDump;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Helper class to store a set of harmful CRC32s in memory.
+ * TODO: Optimize memory usage using int array with binary search.
+ */
+class HarmfulCrcs {
+
+    private final Set<Integer> mCrcSet;
+
+    HarmfulCrcs(List<byte[]> digests) {
+        final HashSet<Integer> crcSet = new HashSet<>();
+        final int size = digests.size();
+        for (int i = 0; i < size; i++) {
+            byte[] bytes = digests.get(i);
+            if (bytes.length <= 4) {
+                int crc = 0;
+                for (byte b : bytes) {
+                    // Remember byte is signed
+                    crc = (crc << 8) | (b & 0xff);
+                }
+                crcSet.add(crc);
+            }
+        }
+        mCrcSet = Collections.unmodifiableSet(crcSet);
+    }
+
+    public boolean contains(int crc) {
+        return mCrcSet.contains(crc);
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        for (int crc : mCrcSet) {
+            pw.println(HexDump.toHexString(crc));
+        }
+        pw.println("");
+    }
+}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
index 8352ca6..7d06de3 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
@@ -18,7 +18,6 @@
 
 import android.annotation.Nullable;
 import android.os.FileUtils;
-import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
@@ -66,11 +65,11 @@
     }
 
     private static class CrcShaDigests {
-        final HarmfulDigests crc32Digests;
-        final HarmfulDigests sha256Digests;
+        public final HarmfulCrcs crc32s;
+        public final HarmfulDigests sha256Digests;
 
-        public CrcShaDigests(HarmfulDigests crc32Digests, HarmfulDigests sha256Digests) {
-            this.crc32Digests = crc32Digests;
+        CrcShaDigests(HarmfulCrcs crc32s, HarmfulDigests sha256Digests) {
+            this.crc32s = crc32s;
             this.sha256Digests = sha256Digests;
         }
     }
@@ -140,9 +139,9 @@
                 }
             }
             parser.require(XmlPullParser.END_TAG, null, XmlTags.WATCHLIST_CONFIG);
-            mDomainDigests = new CrcShaDigests(new HarmfulDigests(crc32DomainList),
+            mDomainDigests = new CrcShaDigests(new HarmfulCrcs(crc32DomainList),
                     new HarmfulDigests(sha256DomainList));
-            mIpDigests = new CrcShaDigests(new HarmfulDigests(crc32IpList),
+            mIpDigests = new CrcShaDigests(new HarmfulCrcs(crc32IpList),
                     new HarmfulDigests(sha256IpList));
             Log.i(TAG, "Reload watchlist done");
         } catch (IllegalStateException | NullPointerException | NumberFormatException |
@@ -171,8 +170,8 @@
             return false;
         }
         // First it does a quick CRC32 check.
-        final byte[] crc32 = getCrc32(domain);
-        if (!domainDigests.crc32Digests.contains(crc32)) {
+        final int crc32 = getCrc32(domain);
+        if (!domainDigests.crc32s.contains(crc32)) {
             return false;
         }
         // Now we do a slow SHA256 check.
@@ -187,8 +186,8 @@
             return false;
         }
         // First it does a quick CRC32 check.
-        final byte[] crc32 = getCrc32(ip);
-        if (!ipDigests.crc32Digests.contains(crc32)) {
+        final int crc32 = getCrc32(ip);
+        if (!ipDigests.crc32s.contains(crc32)) {
             return false;
         }
         // Now we do a slow SHA256 check.
@@ -198,15 +197,11 @@
 
 
     /** Get CRC32 of a string
-     *
-     * TODO: Review if we should use CRC32 or other algorithms
      */
-    private byte[] getCrc32(String str) {
+    private int getCrc32(String str) {
         final CRC32 crc = new CRC32();
         crc.update(str.getBytes());
-        final long tmp = crc.getValue();
-        return new byte[]{(byte) (tmp >> 24 & 255), (byte) (tmp >> 16 & 255),
-                (byte) (tmp >> 8 & 255), (byte) (tmp & 255)};
+        return (int) crc.getValue();
     }
 
     /** Get SHA256 of a string */
@@ -279,7 +274,7 @@
         pw.println("Domain CRC32 digest list:");
         // mDomainDigests won't go from non-null to null so it's safe
         if (mDomainDigests != null) {
-            mDomainDigests.crc32Digests.dump(fd, pw, args);
+            mDomainDigests.crc32s.dump(fd, pw, args);
         }
         pw.println("Domain SHA256 digest list:");
         if (mDomainDigests != null) {
@@ -288,7 +283,7 @@
         pw.println("Ip CRC32 digest list:");
         // mIpDigests won't go from non-null to null so it's safe
         if (mIpDigests != null) {
-            mIpDigests.crc32Digests.dump(fd, pw, args);
+            mIpDigests.crc32s.dump(fd, pw, args);
         }
         pw.println("Ip SHA256 digest list:");
         if (mIpDigests != null) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ca979f8..0fc1718 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5112,8 +5112,8 @@
         }
         if (contentViewSize >= mStripRemoteViewsSizeBytes) {
             mUsageStats.registerImageRemoved(pkg);
-            Slog.w(TAG,
-                    "Removed too large RemoteViews on pkg: " + pkg + " tag: " + tag + " id: " + id);
+            Slog.w(TAG, "Removed too large RemoteViews (" + contentViewSize + " bytes) on pkg: "
+                    + pkg + " tag: " + tag + " id: " + id);
             return true;
         }
         return false;
@@ -7826,6 +7826,7 @@
                 R.array.config_allowedManagedServicesOnLowRamDevices)) {
             if (whitelisted.equals(pkg)) {
                 canUseManagedServices = true;
+                break;
             }
         }
 
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 714bbb9..9a1b30d 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -25,7 +25,6 @@
 import android.os.BugreportParams;
 import android.os.IDumpstate;
 import android.os.IDumpstateListener;
-import android.os.IDumpstateToken;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -64,13 +63,6 @@
 
     @Override
     @RequiresPermission(android.Manifest.permission.DUMP)
-    public IDumpstateToken setListener(String name, IDumpstateListener listener,
-            boolean getSectionDetails) {
-        throw new UnsupportedOperationException("setListener is not allowed on this service");
-    }
-
-    @Override
-    @RequiresPermission(android.Manifest.permission.DUMP)
     public void startBugreport(int callingUidUnused, String callingPackage,
             FileDescriptor bugreportFd, FileDescriptor screenshotFd,
             int bugreportMode, IDumpstateListener listener) {
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index dc00cb4..12e8069 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -32,12 +32,14 @@
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
+import android.os.Environment;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.sysprop.ApexProperties;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -46,6 +48,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -63,9 +66,9 @@
     static final int MATCH_FACTORY_PACKAGE = 1 << 1;
 
     /**
-     * Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerNoOp} depending
-     * on whenever this device supports APEX, i.e. {@link ApexProperties#updatable()} evaluates to
-     * {@code true}.
+     * Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerFlattenedApex}
+     * depending on whether this device supports APEX, i.e. {@link ApexProperties#updatable()}
+     * evaluates to {@code true}.
      */
     static ApexManager create(Context systemContext) {
         if (ApexProperties.updatable().orElse(false)) {
@@ -76,10 +79,28 @@
                 throw new IllegalStateException("Required service apexservice not available");
             }
         } else {
-            return new ApexManagerNoOp();
+            return new ApexManagerFlattenedApex();
         }
     }
 
+    /**
+     * Minimal information about APEX mount points and the original APEX package they refer to.
+     */
+    static class ActiveApexInfo {
+        public final File apexDirectory;
+        public final File preinstalledApexPath;
+
+        private ActiveApexInfo(File apexDirectory, File preinstalledApexPath) {
+            this.apexDirectory = apexDirectory;
+            this.preinstalledApexPath = preinstalledApexPath;
+        }
+    }
+
+    /**
+     * Returns {@link ActiveApexInfo} records relative to all active APEX packages.
+     */
+    abstract List<ActiveApexInfo> getActiveApexInfos();
+
     abstract void systemReady();
 
     /**
@@ -217,7 +238,8 @@
      * An implementation of {@link ApexManager} that should be used in case device supports updating
      * APEX packages.
      */
-    private static class ApexManagerImpl extends ApexManager {
+    @VisibleForTesting
+    static class ApexManagerImpl extends ApexManager {
         private final IApexService mApexService;
         private final Context mContext;
         private final Object mLock = new Object();
@@ -257,6 +279,22 @@
         }
 
         @Override
+        List<ActiveApexInfo> getActiveApexInfos() {
+            try {
+                return Arrays.stream(mApexService.getActivePackages())
+                        .map(apexInfo -> new ActiveApexInfo(
+                                new File(
+                                Environment.getApexDirectory() + File.separator
+                                        + apexInfo.moduleName),
+                                new File(apexInfo.modulePath))).collect(
+                                Collectors.toList());
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to retrieve packages from apexservice", e);
+            }
+            return Collections.emptyList();
+        }
+
+        @Override
         void systemReady() {
             mContext.registerReceiver(new BroadcastReceiver() {
                 @Override
@@ -335,8 +373,8 @@
                 if (!packageInfo.packageName.equals(packageName)) {
                     continue;
                 }
-                if ((!matchActive || isActive(packageInfo))
-                        && (!matchFactory || isFactory(packageInfo))) {
+                if ((matchActive && isActive(packageInfo))
+                        || (matchFactory && isFactory(packageInfo))) {
                     return packageInfo;
                 }
             }
@@ -547,7 +585,40 @@
      * An implementation of {@link ApexManager} that should be used in case device does not support
      * updating APEX packages.
      */
-    private static final class ApexManagerNoOp extends ApexManager {
+    private static final class ApexManagerFlattenedApex extends ApexManager {
+
+        @Override
+        List<ActiveApexInfo> getActiveApexInfos() {
+            // There is no apexd running in case of flattened apex
+            // We look up the /apex directory and identify the active APEX modules from there.
+            // As "preinstalled" path, we just report /system since in the case of flattened APEX
+            // the /apex directory is just a symlink to /system/apex.
+            List<ActiveApexInfo> result = new ArrayList<>();
+            File apexDir = Environment.getApexDirectory();
+            // In flattened configuration, init special-case the art directory and bind-mounts
+            // com.android.art.{release|debug} to com.android.art. At the time of writing, these
+            // directories are copied from the kArtApexDirNames variable in
+            // system/core/init/mount_namespace.cpp.
+            String[] skipDirs = {"com.android.art.release", "com.android.art.debug"};
+            if (apexDir.isDirectory()) {
+                File[] files = apexDir.listFiles();
+                // listFiles might be null if system server doesn't have permission to read
+                // a directory.
+                if (files != null) {
+                    for (File file : files) {
+                        if (file.isDirectory() && !file.getName().contains("@")) {
+                            for (String skipDir : skipDirs) {
+                                if (file.getName().equals(skipDir)) {
+                                    continue;
+                                }
+                            }
+                            result.add(new ActiveApexInfo(file, Environment.getRootDirectory()));
+                        }
+                    }
+                }
+            }
+            return result;
+        }
 
         @Override
         void systemReady() {
diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java
index b0cf525..990eba1 100644
--- a/services/core/java/com/android/server/pm/InstallSource.java
+++ b/services/core/java/com/android/server/pm/InstallSource.java
@@ -20,40 +20,103 @@
 
 import com.android.internal.util.IndentingPrintWriter;
 
+import java.util.Objects;
+
 /**
  * Immutable class holding information about where the request to install or update an app
  * came from.
  */
 final class InstallSource {
-    private static final InstallSource EMPTY = new InstallSource(null);
-
     /**
-     * The package that requested the installation, if known.
+     * An instance of InstallSource representing an absence of knowledge of the source of
+     * a package. Used in preference to null.
      */
+    static final InstallSource EMPTY = new InstallSource(null, null, false);
+
+    /** The package that requested the installation, if known. */
     @Nullable
     final String initiatingPackageName;
 
-    static InstallSource create(@Nullable String initiatingPackageName) {
-        return initiatingPackageName == null
-                ? EMPTY : new InstallSource(initiatingPackageName.intern());
+    /**
+     * Package name of the app that installed this package (the installer of record). Note that
+     * this may be modified.
+     */
+    @Nullable
+    final String installerPackageName;
+
+    /** Indicates if the package that was the installerPackageName has been uninstalled. */
+    final boolean isOrphaned;
+
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName) {
+        return create(initiatingPackageName, installerPackageName, false);
     }
 
-    private InstallSource(@Nullable String initiatingPackageName) {
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName, boolean isOrphaned) {
+        if (initiatingPackageName == null && installerPackageName == null && !isOrphaned) {
+            return EMPTY;
+        }
+        return new InstallSource(
+                initiatingPackageName == null ? null : initiatingPackageName.intern(),
+                installerPackageName == null ? null : installerPackageName.intern(),
+                isOrphaned);
+    }
+
+    private InstallSource(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName, boolean isOrphaned) {
         this.initiatingPackageName = initiatingPackageName;
+        this.isOrphaned = isOrphaned;
+        this.installerPackageName = installerPackageName;
     }
 
     void dump(IndentingPrintWriter pw) {
+        pw.printPair("installerPackageName", installerPackageName);
         pw.printPair("installInitiatingPackageName", initiatingPackageName);
     }
 
     /**
+     * Return an InstallSource the same as this one except with the specified installerPackageName.
+     */
+    InstallSource setInstallerPackage(String installerPackageName) {
+        return Objects.equals(installerPackageName, this.installerPackageName) ? this
+                : create(initiatingPackageName, installerPackageName, isOrphaned);
+    }
+
+    /**
+     * Return an InstallSource the same as this one except with the specified value for isOrphaned.
+     */
+    InstallSource setIsOrphaned(boolean isOrphaned) {
+        return isOrphaned == this.isOrphaned ? this
+                : create(initiatingPackageName, installerPackageName, isOrphaned);
+    }
+
+    /**
      * Return an InstallSource the same as this one except it does not refer to the specified
-     * installer package name.
+     * installer package name (which is being uninstalled).
      */
     InstallSource removeInstallerPackage(String packageName) {
-        if (packageName != null && packageName.equals(initiatingPackageName)) {
-            return create(null);
+        if (packageName == null) {
+            return this;
         }
-        return this;
+
+        boolean modified = false;
+        String initiatingPackageName = this.initiatingPackageName;
+        String installerPackageName = this.installerPackageName;
+        boolean isOrphaned = this.isOrphaned;
+
+        if (packageName.equals(initiatingPackageName)) {
+            initiatingPackageName = null;
+            modified = true;
+        }
+        if (packageName.equals(installerPackageName)) {
+            installerPackageName = null;
+            isOrphaned = true;
+            modified = true;
+        }
+
+        return modified
+                ? create(initiatingPackageName, installerPackageName, isOrphaned)
+                : this;
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index 1d3d24c..259200b 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -67,6 +67,15 @@
             codeRoot = Environment.getSystemExtDirectory();
         } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) {
             codeRoot = Environment.getOdmDirectory();
+        } else if (FileUtils.contains(Environment.getApexDirectory(), codePath)) {
+            String fullPath = codePath.getAbsolutePath();
+            String[] parts = fullPath.split(File.separator);
+            if (parts.length > 2) {
+                codeRoot = new File(parts[1] + File.separator + parts[2]);
+            } else {
+                Slog.w(PackageManagerService.TAG, "Can't canonicalize code path " + codePath);
+                codeRoot = Environment.getApexDirectory();
+            }
         } else {
             // Unrecognized code path; take its top real segment as the apk root:
             // e.g. /something/app/blah.apk => /something
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index eca93bb..ed2bb3d5 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -259,7 +259,7 @@
         // 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()) {
+            if (mPm.isDeviceUpgrading() && !session.isStagedAndInTerminalState()) {
                 session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
                         "Build fingerprint has changed");
             }
@@ -623,10 +623,11 @@
                 stageCid = buildExternalStageCid(sessionId);
             }
         }
-        InstallSource installSource = InstallSource.create(installerPackageName);
+        InstallSource installSource = InstallSource.create(installerPackageName,
+                requestedInstallerPackageName);
         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
-                mInstallThread.getLooper(), mStagingManager, sessionId, userId,
-                requestedInstallerPackageName, callingUid, installSource, params, createdMillis,
+                mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
+                installSource, params, createdMillis,
                 stageDir, stageCid, false, false, false, null, SessionInfo.INVALID_ID,
                 false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, "");
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d8bfa7d..feb1271 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -212,10 +212,6 @@
     /** Uid of the creator of this session. */
     private final int mOriginalInstallerUid;
 
-    /** Package of the owner of the installer session */
-    @GuardedBy("mLock")
-    private @Nullable String mInstallerPackageName;
-
     /** Uid of the owner of the installer session */
     @GuardedBy("mLock")
     private int mInstallerUid;
@@ -374,7 +370,8 @@
         }
         DevicePolicyManagerInternal dpmi =
                 LocalServices.getService(DevicePolicyManagerInternal.class);
-        return dpmi != null && dpmi.canSilentlyInstallPackage(mInstallerPackageName, mInstallerUid);
+        return dpmi != null && dpmi.canSilentlyInstallPackage(
+                mInstallSource.installerPackageName, mInstallerUid);
     }
 
     /**
@@ -418,8 +415,7 @@
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
             Context context, PackageManagerService pm,
             PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
-            int sessionId, int userId,
-            String installerPackageName, int installerUid, @NonNull InstallSource installSource,
+            int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
             SessionParams params, long createdMillis,
             File stageDir, String stageCid, boolean prepared, boolean committed, boolean sealed,
             @Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
@@ -435,7 +431,6 @@
         this.sessionId = sessionId;
         this.userId = userId;
         mOriginalInstallerUid = installerUid;
-        mInstallerPackageName = installerPackageName;
         mInstallerUid = installerUid;
         mInstallSource = Preconditions.checkNotNull(installSource);
         this.params = params;
@@ -475,7 +470,7 @@
         synchronized (mLock) {
             info.sessionId = sessionId;
             info.userId = userId;
-            info.installerPackageName = mInstallerPackageName;
+            info.installerPackageName = mInstallSource.installerPackageName;
             info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
                     mResolvedBaseFile.getAbsolutePath() : null;
             info.progress = mProgress;
@@ -1226,14 +1221,13 @@
                 throw new IllegalArgumentException("Package is not valid", e);
             }
 
-            if (!mPackageName.equals(mInstallerPackageName)) {
+            if (!mPackageName.equals(mInstallSource.installerPackageName)) {
                 throw new SecurityException("Can only transfer sessions that update the original "
                         + "installer");
             }
 
-            mInstallerPackageName = packageName;
             mInstallerUid = newOwnerAppInfo.uid;
-            mInstallSource = InstallSource.create(packageName);
+            mInstallSource = InstallSource.create(packageName, packageName);
         }
 
         // Persist the fact that we've sealed ourselves to prevent
@@ -1246,7 +1240,7 @@
         if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) {
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.INSTALL_PACKAGE)
-                    .setAdmin(mInstallerPackageName)
+                    .setAdmin(mInstallSource.installerPackageName)
                     .write();
         }
         if (params.isStaged) {
@@ -1452,8 +1446,7 @@
 
         mRelinquished = true;
         return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
-                localObserver, params, mInstallerPackageName, mInstallerUid, mInstallSource, user,
-                mSigningDetails);
+                localObserver, params, mInstallerUid, mInstallSource, user, mSigningDetails);
     }
 
     private static void maybeRenameFile(File from, File to) throws PackageManagerException {
@@ -1902,7 +1895,7 @@
 
     String getInstallerPackageName() {
         synchronized (mLock) {
-            return mInstallerPackageName;
+            return mInstallSource.installerPackageName;
         }
     }
 
@@ -2343,9 +2336,8 @@
 
         pw.printPair("userId", userId);
         pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid);
-        pw.printPair("mInstallerPackageName", mInstallerPackageName);
-        pw.printPair("mInstallerUid", mInstallerUid);
         mInstallSource.dump(pw);
+        pw.printPair("mInstallerUid", mInstallerUid);
         pw.printPair("createdMillis", createdMillis);
         pw.printPair("updatedMillis", updatedMillis);
         pw.printPair("stageDir", stageDir);
@@ -2424,7 +2416,7 @@
             writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
             writeIntAttribute(out, ATTR_USER_ID, userId);
             writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
-                    mInstallerPackageName);
+                    mInstallSource.installerPackageName);
             writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid);
             writeStringAttribute(out, ATTR_INITIATING_PACKAGE_NAME,
                     mInstallSource.initiatingPackageName);
@@ -2626,10 +2618,11 @@
             childSessionIdsArray = EMPTY_CHILD_SESSION_ARRAY;
         }
 
-        InstallSource installSource = InstallSource.create(installInitiatingPackageName);
+        InstallSource installSource = InstallSource.create(installInitiatingPackageName,
+                installerPackageName);
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
-                installerThread, stagingManager, sessionId, userId, installerPackageName,
-                installerUid, installSource, params, createdMillis, stageDir, stageCid,
+                installerThread, stagingManager, sessionId, userId, installerUid,
+                installSource, params, createdMillis, stageDir, stageCid,
                 prepared, committed, sealed, childSessionIdsArray, parentSessionId,
                 isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage);
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d057aa2..74a85d5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -370,6 +370,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 
 /**
  * Keep track of all those APKs everywhere.
@@ -762,6 +763,8 @@
                     new SystemPartition(Environment.getSystemExtDirectory(), SCAN_AS_SYSTEM_EXT,
                             true /* hasPriv */, true /* hasOverlays */)));
 
+    private final List<SystemPartition> mDirsToScanAsSystem;
+
     /**
      * Unit tests will instantiate, extend and/or mock to mock dependencies / behaviors.
      *
@@ -1562,8 +1565,8 @@
                     }
                     // Send broadcasts
                     for (int i = 0; i < size; i++) {
-                        sendPackageChangedBroadcast(packages[i], true, components[i], uids[i],
-                                null);
+                        sendPackageChangedBroadcast(packages[i], true /* dontKillApp */,
+                                components[i], uids[i], null /* reason */);
                     }
                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                     break;
@@ -1598,7 +1601,7 @@
                         handlePackagePostInstall(parentRes, grantPermissions,
                                 killApp, virtualPreload, grantedPermissions,
                                 whitelistedRestrictedPermissions, didRestore,
-                                args.installerPackageName, args.observer);
+                                args.installSource.installerPackageName, args.observer);
 
                         // Handle the child packages
                         final int childCount = (parentRes.addedChildPackages != null)
@@ -1608,7 +1611,7 @@
                             handlePackagePostInstall(childRes, grantPermissions,
                                     killApp, virtualPreload, grantedPermissions,
                                     whitelistedRestrictedPermissions, false /*didRestore*/,
-                                    args.installerPackageName, args.observer);
+                                    args.installSource.installerPackageName, args.observer);
                         }
 
                         // Log tracing if needed
@@ -2049,7 +2052,7 @@
                 for (int i = 0; i < res.libraryConsumers.size(); i++) {
                     PackageParser.Package pkg = res.libraryConsumers.get(i);
                     // send broadcast that all consumers of the static shared library have changed
-                    sendPackageChangedBroadcast(pkg.packageName, false /*killFlag*/,
+                    sendPackageChangedBroadcast(pkg.packageName, false /* dontKillApp */,
                             new ArrayList<>(Collections.singletonList(pkg.packageName)),
                             pkg.applicationInfo.uid, null);
                 }
@@ -2552,6 +2555,16 @@
         mApexManager = ApexManager.create(mContext);
         mAppsFilter = mInjector.getAppsFilter();
 
+        mDirsToScanAsSystem = new ArrayList<>();
+        mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
+        mDirsToScanAsSystem.addAll(mApexManager.getActiveApexInfos().stream()
+                .map(ai -> resolveApexToSystemPartition(ai))
+                .filter(Objects::nonNull).collect(Collectors.toList()));
+        Slog.d(TAG,
+                "Directories scanned as system partitions: [" + mDirsToScanAsSystem.stream().map(
+                        d -> (d.folder.getAbsolutePath() + ":" + d.scanFlag))
+                        .collect(Collectors.joining(",")) + "]");
+
         // CHECKSTYLE:OFF IndentationCheck
         synchronized (mInstallLock) {
         // writer
@@ -2684,8 +2697,8 @@
             // reside in the right directory.
             final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
             final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
-            for (int i = SYSTEM_PARTITIONS.size() - 1; i >= 0; i--) {
-                final SystemPartition partition = SYSTEM_PARTITIONS.get(i);
+            for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
+                final SystemPartition partition = mDirsToScanAsSystem.get(i);
                 if (partition.overlayFolder == null) {
                     continue;
                 }
@@ -2699,8 +2712,8 @@
                 throw new IllegalStateException(
                         "Failed to load frameworks package; check log for warnings");
             }
-            for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
-                final SystemPartition partition = SYSTEM_PARTITIONS.get(i);
+            for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
+                final SystemPartition partition = mDirsToScanAsSystem.get(i);
                 if (partition.privAppFolder != null) {
                     scanDirTracedLI(partition.privAppFolder, systemParseFlags,
                             systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0);
@@ -2878,8 +2891,8 @@
 
                         @ParseFlags int reparseFlags = 0;
                         @ScanFlags int rescanFlags = 0;
-                        for (int i1 = 0, size = SYSTEM_PARTITIONS.size(); i1 < size; i1++) {
-                            SystemPartition partition = SYSTEM_PARTITIONS.get(i1);
+                        for (int i1 = 0, size = mDirsToScanAsSystem.size(); i1 < size; i1++) {
+                            SystemPartition partition = mDirsToScanAsSystem.get(i1);
                             if (partition.containsPrivApp(scanFile)) {
                                 reparseFlags = systemParseFlags;
                                 rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
@@ -4037,7 +4050,7 @@
     private PackageInfo getPackageInfoInternal(String packageName, long versionCode,
             int flags, int filterCallingUid, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForPackage(flags, userId, packageName);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
 
@@ -4092,7 +4105,7 @@
                 }
                 return generatePackageInfo(ps, flags, userId);
             }
-            if (!matchFactoryOnly && (flags & MATCH_APEX) != 0) {
+            if ((flags & MATCH_APEX) != 0) {
                 return mApexManager.getPackageInfo(packageName, ApexManager.MATCH_ACTIVE_PACKAGE);
             }
         }
@@ -4339,7 +4352,7 @@
     public int getPackageUid(String packageName, int flags, int userId) {
         if (!mUserManager.exists(userId)) return -1;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForPackage(flags, userId, packageName);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /*requireFullPermission*/, false /*checkShell*/, "getPackageUid");
 
@@ -4369,7 +4382,7 @@
     public int[] getPackageGids(String packageName, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForPackage(flags, userId, packageName);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /*requireFullPermission*/, false /*checkShell*/, "getPackageGids");
 
@@ -4451,7 +4464,7 @@
     private ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
             int filterCallingUid, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForApplication(flags, userId, packageName);
+        flags = updateFlagsForApplication(flags, userId);
 
         if (!isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId)) {
             mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -4738,7 +4751,7 @@
     /**
      * Update given flags when being used to request {@link PackageInfo}.
      */
-    private int updateFlagsForPackage(int flags, int userId, Object cookie) {
+    private int updateFlagsForPackage(int flags, int userId) {
         final boolean isCallerSystemUser = UserHandle.getCallingUserId() == UserHandle.USER_SYSTEM;
         if ((flags & PackageManager.MATCH_ANY_USER) != 0) {
             // require the permission to be held; the calling uid and given user id referring
@@ -4762,14 +4775,14 @@
     /**
      * Update given flags when being used to request {@link ApplicationInfo}.
      */
-    private int updateFlagsForApplication(int flags, int userId, Object cookie) {
-        return updateFlagsForPackage(flags, userId, cookie);
+    private int updateFlagsForApplication(int flags, int userId) {
+        return updateFlagsForPackage(flags, userId);
     }
 
     /**
      * Update given flags when being used to request {@link ComponentInfo}.
      */
-    private int updateFlagsForComponent(int flags, int userId, Object cookie) {
+    private int updateFlagsForComponent(int flags, int userId) {
         return updateFlags(flags, userId);
     }
 
@@ -4798,16 +4811,12 @@
      * action and a {@code android.intent.category.BROWSABLE} category</li>
      * </ul>
      */
-    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid) {
-        return updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*wantInstantApps*/, false /*onlyExposedExplicitly*/);
-    }
-    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
-            boolean wantInstantApps) {
-        return updateFlagsForResolve(flags, userId, intent, callingUid,
+    int updateFlagsForResolve(int flags, int userId, int callingUid, boolean wantInstantApps) {
+        return updateFlagsForResolve(flags, userId, callingUid,
                 wantInstantApps, false /*onlyExposedExplicitly*/);
     }
-    int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
+
+    int updateFlagsForResolve(int flags, int userId, int callingUid,
             boolean wantInstantApps, boolean onlyExposedExplicitly) {
         // Safe mode means we shouldn't match any third-party components
         if (mSafeMode) {
@@ -4830,7 +4839,7 @@
                 flags &= ~PackageManager.MATCH_INSTANT;
             }
         }
-        return updateFlagsForComponent(flags, userId, intent /*cookie*/);
+        return updateFlagsForComponent(flags, userId);
     }
 
     @Override
@@ -4847,7 +4856,7 @@
     private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
             int filterCallingUid, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
 
         if (!isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId)) {
             mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -4928,7 +4937,7 @@
     public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get receiver info");
         synchronized (mLock) {
@@ -4958,7 +4967,7 @@
             return null;
         }
 
-        flags = updateFlagsForPackage(flags, userId, null);
+        flags = updateFlagsForPackage(flags, userId);
 
         final boolean canSeeStaticLibraries =
                 mContext.checkCallingOrSelfPermission(INSTALL_PACKAGES)
@@ -5143,7 +5152,7 @@
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get service info");
         synchronized (mLock) {
@@ -5168,7 +5177,7 @@
     public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForComponent(flags, userId, component);
+        flags = updateFlagsForComponent(flags, userId);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get provider info");
         synchronized (mLock) {
@@ -5868,7 +5877,7 @@
 
             if (!mUserManager.exists(userId)) return null;
             final int callingUid = Binder.getCallingUid();
-            flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
+            flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart);
             mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                     false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
 
@@ -5898,7 +5907,7 @@
         intent = updateIntentForResolve(intent);
         final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
         final int flags = updateFlagsForResolve(
-                0, userId, intent, callingUid, false /*includeInstantApps*/);
+                0, userId, callingUid, false /*includeInstantApps*/);
         final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
                 userId);
         synchronized (mLock) {
@@ -6212,7 +6221,7 @@
                 android.provider.Settings.Global.getInt(mContext.getContentResolver(),
                         android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
         flags = updateFlagsForResolve(
-                flags, userId, intent, callingUid, false /*includeInstantApps*/);
+                flags, userId, callingUid, false /*includeInstantApps*/);
         intent = updateIntentForResolve(intent);
         // writer
         synchronized (mLock) {
@@ -6420,7 +6429,7 @@
             final int callingUid = Binder.getCallingUid();
             final UserInfo parent = getProfileParent(sourceUserId);
             synchronized (mLock) {
-                int flags = updateFlagsForResolve(0, parent.id, intent, callingUid,
+                int flags = updateFlagsForResolve(0, parent.id, callingUid,
                         false /*includeInstantApps*/);
                 CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr(
                         intent, resolvedType, flags, sourceUserId, parent.id);
@@ -6506,7 +6515,7 @@
             }
         }
 
-        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart,
+        flags = updateFlagsForResolve(flags, userId, filterCallingUid, resolveForStart,
                 comp != null || pkgName != null /*onlyExposedExplicitly*/);
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<>(1);
@@ -7273,8 +7282,7 @@
             String resolvedType, int flags, int userId) {
         if (!mUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /*requireFullPermission*/, false /*checkShell*/,
                 "query intent activity options");
@@ -7460,8 +7468,7 @@
                 false /*requireFullPermission*/, false /*checkShell*/,
                 "query intent receivers");
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7551,8 +7558,7 @@
     private ResolveInfo resolveServiceInternal(Intent intent, String resolvedType, int flags,
             int userId, int callingUid) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForResolve(
-                flags, userId, intent, callingUid, false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         List<ResolveInfo> query = queryIntentServicesInternal(
                 intent, resolvedType, flags, userId, callingUid, false /*includeInstantApps*/);
         if (query != null) {
@@ -7581,7 +7587,7 @@
                 false /*requireFullPermission*/, false /*checkShell*/,
                 "query intent receivers");
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid, includeInstantApps);
+        flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7708,8 +7714,7 @@
         if (!mUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/);
+        flags = updateFlagsForResolve(flags, userId, callingUid, false /*includeInstantApps*/);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -7831,7 +7836,7 @@
             return ParceledListSlice.emptyList();
         }
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
-        flags = updateFlagsForPackage(flags, userId, null);
+        flags = updateFlagsForPackage(flags, userId);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
         final boolean listApex = (flags & MATCH_APEX) != 0;
         final boolean listFactory = (flags & MATCH_FACTORY_ONLY) != 0;
@@ -7931,7 +7936,7 @@
     public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
             String[] permissions, int flags, int userId) {
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
-        flags = updateFlagsForPackage(flags, userId, permissions);
+        flags = updateFlagsForPackage(flags, userId);
         mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "get packages holding permissions");
@@ -7973,7 +7978,7 @@
             return Collections.emptyList();
         }
         if (!mUserManager.exists(userId)) return Collections.emptyList();
-        flags = updateFlagsForApplication(flags, userId, null);
+        flags = updateFlagsForApplication(flags, userId);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
 
         mPermissionManager.enforceCrossUserPermission(
@@ -8208,7 +8213,7 @@
 
     private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId) {
         if (!mUserManager.exists(userId)) return null;
-        flags = updateFlagsForComponent(flags, userId, name);
+        flags = updateFlagsForComponent(flags, userId);
         final int callingUid = Binder.getCallingUid();
         final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
         if (providerInfo == null) {
@@ -8247,7 +8252,7 @@
         final int userId = processName != null ? UserHandle.getUserId(uid)
                 : UserHandle.getCallingUserId();
         if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
-        flags = updateFlagsForComponent(flags, userId, processName);
+        flags = updateFlagsForComponent(flags, userId);
         ArrayList<ProviderInfo> finalList = null;
         final List<ProviderInfo> matchList =
                 mComponentResolver.queryProviders(processName, metaDataKey, uid, flags, userId);
@@ -10907,7 +10912,7 @@
         }
 
         if (isSystemApp(pkg)) {
-            pkgSetting.isOrphaned = true;
+            pkgSetting.setIsOrphaned(true);
         }
 
         // Take care of first install / last update times.
@@ -12390,7 +12395,7 @@
             int userId) {
         final PackageRemovedInfo info = new PackageRemovedInfo(this);
         info.removedPackage = packageName;
-        info.installerPackageName = pkgSetting.installerPackageName;
+        info.installerPackageName = pkgSetting.installSource.installerPackageName;
         info.removedUsers = new int[] {userId};
         info.broadcastUsers = new int[] {userId};
         info.uid = UserHandle.getUid(userId, pkgSetting.appId);
@@ -13412,9 +13417,11 @@
 
             // Verify: if target already has an installer package, it must
             // be signed with the same cert as the caller.
-            if (targetPackageSetting.installerPackageName != null) {
+            String targetInstallerPackageName =
+                    targetPackageSetting.installSource.installerPackageName;
+            if (targetInstallerPackageName != null) {
                 PackageSetting setting = mSettings.mPackages.get(
-                        targetPackageSetting.installerPackageName);
+                        targetInstallerPackageName);
                 // If the currently set package isn't valid, then it's always
                 // okay to change it.
                 if (setting != null) {
@@ -13423,13 +13430,13 @@
                             != PackageManager.SIGNATURE_MATCH) {
                         throw new SecurityException(
                                 "Caller does not have same cert as old installer package "
-                                + targetPackageSetting.installerPackageName);
+                                + targetInstallerPackageName);
                     }
                 }
             }
 
             // Okay!
-            targetPackageSetting.installerPackageName = installerPackageName;
+            targetPackageSetting.setInstallerPackageName(installerPackageName);
             if (installerPackageName != null) {
                 mSettings.mInstallerPackages.add(installerPackageName);
             }
@@ -13454,7 +13461,7 @@
                     ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
                 throw new IllegalArgumentException("Unknown target package " + packageName);
             }
-            if (!Objects.equals(callerPackageName, ps.installerPackageName)) {
+            if (!Objects.equals(callerPackageName, ps.installSource.installerPackageName)) {
                 throw new IllegalArgumentException("Calling package " + callerPackageName
                         + " is not installer for " + packageName);
             }
@@ -13914,8 +13921,7 @@
         final MoveInfo move;
         final IPackageInstallObserver2 observer;
         int installFlags;
-        final String installerPackageName;
-        final InstallSource installSource;
+        @NonNull final InstallSource installSource;
         final String volumeUuid;
         private boolean mVerificationCompleted;
         private boolean mEnableRollbackCompleted;
@@ -13932,8 +13938,7 @@
         final long requiredInstalledVersionCode;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
-                int installFlags, String installerPackageName,
-                InstallSource installSource, String volumeUuid,
+                int installFlags, InstallSource installSource, String volumeUuid,
                 VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
                 String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
                 SigningDetails signingDetails, int installReason,
@@ -13943,8 +13948,7 @@
             this.move = move;
             this.observer = observer;
             this.installFlags = installFlags;
-            this.installerPackageName = installerPackageName;
-            this.installSource = installSource;
+            this.installSource = Preconditions.checkNotNull(installSource);
             this.volumeUuid = volumeUuid;
             this.verificationInfo = verificationInfo;
             this.packageAbiOverride = packageAbiOverride;
@@ -13970,12 +13974,12 @@
                     activeInstallSession.getInstallerUid());
             origin = OriginInfo.fromStagedFile(activeInstallSession.getStagedDir());
             move = null;
-            installReason = fixUpInstallReason(activeInstallSession.getInstallerPackageName(),
+            installReason = fixUpInstallReason(
+                    activeInstallSession.getInstallSource().installerPackageName,
                     activeInstallSession.getInstallerUid(),
                     activeInstallSession.getSessionParams().installReason);
             observer = activeInstallSession.getObserver();
             installFlags = activeInstallSession.getSessionParams().installFlags;
-            installerPackageName = activeInstallSession.getInstallerPackageName();
             installSource = activeInstallSession.getInstallSource();
             volumeUuid = activeInstallSession.getSessionParams().volumeUuid;
             packageAbiOverride = activeInstallSession.getSessionParams().abiOverride;
@@ -14227,7 +14231,7 @@
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
-                            installerPackageName);
+                            installSource.installerPackageName);
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
                             installFlags);
@@ -14458,8 +14462,7 @@
         final IPackageInstallObserver2 observer;
         // Always refers to PackageManager flags only
         final int installFlags;
-        final String installerPackageName;
-        final InstallSource installSource;
+        @NonNull final InstallSource installSource;
         final String volumeUuid;
         final UserHandle user;
         final String abiOverride;
@@ -14478,8 +14481,7 @@
         /* nullable */ String[] instructionSets;
 
         InstallArgs(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
-                int installFlags, String installerPackageName,
-                InstallSource installSource, String volumeUuid,
+                int installFlags, InstallSource installSource, String volumeUuid,
                 UserHandle user, String[] instructionSets,
                 String abiOverride, String[] installGrantPermissions,
                 List<String> whitelistedRestrictedPermissions,
@@ -14490,8 +14492,7 @@
             this.move = move;
             this.installFlags = installFlags;
             this.observer = observer;
-            this.installerPackageName = installerPackageName;
-            this.installSource = installSource;
+            this.installSource = Preconditions.checkNotNull(installSource);
             this.volumeUuid = volumeUuid;
             this.user = user;
             this.instructionSets = instructionSets;
@@ -14508,7 +14509,7 @@
         /** New install */
         InstallArgs(InstallParams params) {
             this(params.origin, params.move, params.observer, params.installFlags,
-                    params.installerPackageName, params.installSource, params.volumeUuid,
+                    params.installSource, params.volumeUuid,
                     params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
                     params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
                     params.traceMethod, params.traceCookie, params.signingDetails,
@@ -14600,8 +14601,9 @@
 
         /** Existing install */
         FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
-            super(OriginInfo.fromNothing(), null, null, 0, null, null, null, null, instructionSets,
-                    null, null, null, null, 0, PackageParser.SigningDetails.UNKNOWN,
+            super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
+                    null, null, instructionSets, null, null, null, null, 0,
+                    PackageParser.SigningDetails.UNKNOWN,
                     PackageManager.INSTALL_REASON_UNKNOWN, null /* parent */);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
@@ -15057,7 +15059,7 @@
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
 
         final String pkgName = pkg.packageName;
-        final String installerPackageName = installArgs.installerPackageName;
+        final String installerPackageName = installArgs.installSource.installerPackageName;
         final int[] installedForUsers = res.origUsers;
         final int installReason = installArgs.installReason;
 
@@ -15825,7 +15827,8 @@
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
                 request.installResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
-                request.installResult.installerPackageName = request.args.installerPackageName;
+                request.installResult.installerPackageName =
+                        request.args.installSource.installerPackageName;
 
                 final String packageName = prepareResult.packageToScan.packageName;
                 prepareResults.put(packageName, prepareResult);
@@ -16171,7 +16174,8 @@
                     if ((mPackages.containsKey(childPkg.packageName))) {
                         childRes.removedInfo = new PackageRemovedInfo(this);
                         childRes.removedInfo.removedPackage = childPkg.packageName;
-                        childRes.removedInfo.installerPackageName = childPs.installerPackageName;
+                        childRes.removedInfo.installerPackageName =
+                                childPs.installSource.installerPackageName;
                     }
                     if (res.addedChildPackages == null) {
                         res.addedChildPackages = new ArrayMap<>();
@@ -16619,7 +16623,7 @@
                 res.removedInfo = new PackageRemovedInfo(this);
                 res.removedInfo.uid = oldPackage.applicationInfo.uid;
                 res.removedInfo.removedPackage = oldPackage.packageName;
-                res.removedInfo.installerPackageName = ps.installerPackageName;
+                res.removedInfo.installerPackageName = ps.installSource.installerPackageName;
                 res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;
                 res.removedInfo.isUpdate = true;
                 res.removedInfo.origUsers = installedUsers;
@@ -16642,7 +16646,7 @@
                                 childRes.removedInfo.removedPackage = childPkg.packageName;
                                 if (childPs != null) {
                                     childRes.removedInfo.installerPackageName =
-                                            childPs.installerPackageName;
+                                            childPs.installSource.installerPackageName;
                                 }
                                 childRes.removedInfo.isUpdate = true;
                                 childRes.removedInfo.installReasons =
@@ -16654,7 +16658,8 @@
                             PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
                             childRemovedRes.removedPackage = childPkg.packageName;
                             if (childPs != null) {
-                                childRemovedRes.installerPackageName = childPs.installerPackageName;
+                                childRemovedRes.installerPackageName =
+                                        childPs.installSource.installerPackageName;
                             }
                             childRemovedRes.isUpdate = false;
                             childRemovedRes.dataRemoved = true;
@@ -17676,7 +17681,7 @@
         final PackageParser.Package deletedPkg = deletedPs.pkg;
         if (outInfo != null) {
             outInfo.removedPackage = packageName;
-            outInfo.installerPackageName = deletedPs.installerPackageName;
+            outInfo.installerPackageName = deletedPs.installSource.installerPackageName;
             outInfo.isStaticSharedLib = deletedPkg != null
                     && deletedPkg.staticSharedLibName != null;
             outInfo.populateUsers(deletedPs == null ? null
@@ -17786,6 +17791,7 @@
     }
 
     static boolean locationIsPrivileged(String path) {
+        // TODO(dariofreni): include APEX partitions when they will support priv apps.
         for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
             SystemPartition partition = SYSTEM_PARTITIONS.get(i);
             if (partition.containsPrivPath(path)) {
@@ -17795,6 +17801,18 @@
         return false;
     }
 
+    private static @Nullable SystemPartition resolveApexToSystemPartition(
+            ApexManager.ActiveApexInfo apexInfo) {
+        for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
+            SystemPartition sp = SYSTEM_PARTITIONS.get(i);
+            if (apexInfo.preinstalledApexPath.getAbsolutePath().startsWith(
+                    sp.folder.getAbsolutePath())) {
+                return new SystemPartition(apexInfo.apexDirectory, sp.scanFlag,
+                        false /* hasPriv */, false /* hasOverlays */);
+            }
+        }
+        return null;
+    }
 
     /*
      * Tries to delete system package.
@@ -17905,8 +17923,8 @@
                 | PackageParser.PARSE_MUST_BE_APK
                 | PackageParser.PARSE_IS_SYSTEM_DIR;
         @ScanFlags int scanFlags = SCAN_AS_SYSTEM;
-        for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
-            SystemPartition partition = SYSTEM_PARTITIONS.get(i);
+        for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
+            SystemPartition partition = mDirsToScanAsSystem.get(i);
             if (partition.containsPath(codePathString)) {
                 scanFlags |= partition.scanFlag;
                 if (partition.containsPrivPath(codePathString)) {
@@ -18271,7 +18289,7 @@
                     String childPackageName = ps.childPackageNames.get(i);
                     PackageRemovedInfo childInfo = new PackageRemovedInfo(this);
                     childInfo.removedPackage = childPackageName;
-                    childInfo.installerPackageName = ps.installerPackageName;
+                    childInfo.installerPackageName = ps.installSource.installerPackageName;
                     outInfo.removedChildPackages.put(childPackageName, childInfo);
                     PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
                     if (childPs != null) {
@@ -18411,7 +18429,7 @@
 
         if (outInfo != null) {
             outInfo.removedPackage = ps.name;
-            outInfo.installerPackageName = ps.installerPackageName;
+            outInfo.installerPackageName = ps.installSource.installerPackageName;
             outInfo.isStaticSharedLib = pkg != null && pkg.staticSharedLibName != null;
             outInfo.removedAppId = ps.appId;
             outInfo.removedUsers = userIds;
@@ -20007,7 +20025,7 @@
     }
 
     private void sendPackageChangedBroadcast(String packageName,
-            boolean killFlag, ArrayList<String> componentNames, int packageUid,
+            boolean dontKillApp, ArrayList<String> componentNames, int packageUid,
             String reason) {
         if (DEBUG_INSTALL)
             Log.v(TAG, "Sending package changed: package=" + packageName + " components="
@@ -20017,7 +20035,7 @@
         String nameList[] = new String[componentNames.size()];
         componentNames.toArray(nameList);
         extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
-        extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
+        extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, dontKillApp);
         extras.putInt(Intent.EXTRA_UID, packageUid);
         if (reason != null) {
             extras.putString(Intent.EXTRA_REASON, reason);
@@ -20290,7 +20308,7 @@
                     return;
                 }
                 sendPackageChangedBroadcast(pkg.packageName,
-                        false /* killFlag */,
+                        true /* dontKillApp */,
                         new ArrayList<>(Collections.singletonList(pkg.packageName)),
                         pkg.applicationInfo.uid,
                         Intent.ACTION_OVERLAY_CHANGED);
@@ -21876,7 +21894,6 @@
 
         final String currentVolumeUuid;
         final File codeFile;
-        final String installerPackageName;
         final InstallSource installSource;
         final String packageAbiOverride;
         final int appId;
@@ -21934,7 +21951,6 @@
 
             isCurrentLocationExternal = isExternal(pkg);
             codeFile = new File(pkg.codePath);
-            installerPackageName = ps.installerPackageName;
             installSource = ps.installSource;
             packageAbiOverride = ps.cpuAbiOverrideString;
             appId = UserHandle.getAppId(pkg.applicationInfo.uid);
@@ -22081,7 +22097,7 @@
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
-                installerPackageName, installSource, volumeUuid, null /*verificationInfo*/, user,
+                installSource, volumeUuid, null /*verificationInfo*/, user,
                 packageAbiOverride, null /*grantedPermissions*/,
                 null /*whitelistedRestrictedPermissions*/, PackageParser.SigningDetails.UNKNOWN,
                 PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.VERSION_CODE_HIGHEST);
@@ -23543,7 +23559,7 @@
                     return false;
                 }
                 final PackageSetting installerPackageSetting =
-                        mSettings.mPackages.get(packageSetting.installerPackageName);
+                        mSettings.mPackages.get(packageSetting.installSource.installerPackageName);
                 return installerPackageSetting != null
                         && UserHandle.isSameApp(installerPackageSetting.appId, callingUid);
             }
@@ -23966,23 +23982,20 @@
         private final File mStagedDir;
         private final IPackageInstallObserver2 mObserver;
         private final PackageInstaller.SessionParams mSessionParams;
-        private final String mInstallerPackageName;
         private final int mInstallerUid;
-        private final InstallSource mInstallSource;
+        @NonNull private final InstallSource mInstallSource;
         private final UserHandle mUser;
         private final SigningDetails mSigningDetails;
 
         ActiveInstallSession(String packageName, File stagedDir, IPackageInstallObserver2 observer,
-                PackageInstaller.SessionParams sessionParams, String installerPackageName,
-                int installerUid, InstallSource installSource,
-                UserHandle user, SigningDetails signingDetails) {
+                PackageInstaller.SessionParams sessionParams, int installerUid,
+                InstallSource installSource, UserHandle user, SigningDetails signingDetails) {
             mPackageName = packageName;
             mStagedDir = stagedDir;
             mObserver = observer;
             mSessionParams = sessionParams;
-            mInstallerPackageName = installerPackageName;
             mInstallerUid = installerUid;
-            mInstallSource = installSource;
+            mInstallSource = Preconditions.checkNotNull(installSource);
             mUser = user;
             mSigningDetails = signingDetails;
         }
@@ -24003,14 +24016,11 @@
             return mSessionParams;
         }
 
-        public String getInstallerPackageName() {
-            return mInstallerPackageName;
-        }
-
         public int getInstallerUid() {
             return mInstallerUid;
         }
 
+        @NonNull
         public InstallSource getInstallSource() {
             return mInstallSource;
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 52a7c6e..f1c84b8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2437,10 +2437,14 @@
             }
         }
         String arg = getNextArg();
-        if (arg == null) {
+        if (arg == null && !preCreateOnly) {
             getErrPrintWriter().println("Error: no user name specified.");
             return 1;
         }
+        if (arg != null && preCreateOnly) {
+            getErrPrintWriter().println("Warning: name is ignored for pre-created users");
+        }
+
         name = arg;
         UserInfo info;
         IUserManager um = IUserManager.Stub.asInterface(
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index be0621b..4fca91a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -187,7 +187,7 @@
         proto.write(PackageProto.VERSION_CODE, versionCode);
         proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime);
         proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime);
-        proto.write(PackageProto.INSTALLER_NAME, installerPackageName);
+        proto.write(PackageProto.INSTALLER_NAME, installSource.installerPackageName);
 
         if (pkg != null) {
             proto.write(PackageProto.VERSION_STRING, pkg.mVersionName);
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index f0857dd..45ab357 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -36,6 +36,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -122,13 +123,8 @@
      */
     Set<String> mOldCodePaths;
 
-    /** Package name of the app that installed this package */
-    String installerPackageName;
-    /** Indicates if the package that installed this app has been uninstalled */
-    boolean isOrphaned;
-    /** Information about the initial install of this package. */
-    @NonNull
-    InstallSource installSource;
+    /** Information about how this package was installed/updated. */
+    @NonNull InstallSource installSource;
     /** UUID of {@link VolumeInfo} hosting this app */
     String volumeUuid;
     /** The category of this app, as hinted by the installer */
@@ -162,7 +158,7 @@
         this.cpuAbiOverrideString = cpuAbiOverrideString;
         this.versionCode = pVersionCode;
         this.signatures = new PackageSignatures();
-        this.installSource = InstallSource.create(null);
+        this.installSource = InstallSource.EMPTY;
     }
 
     /**
@@ -180,28 +176,21 @@
     }
 
     public void setInstallerPackageName(String packageName) {
-        installerPackageName = packageName;
-    }
-
-    public String getInstallerPackageName() {
-        return installerPackageName;
+        installSource = installSource.setInstallerPackage(packageName);
     }
 
     public void setInstallSource(InstallSource installSource) {
-        this.installSource = installSource == null ? InstallSource.create(null) : installSource;
+        this.installSource = Preconditions.checkNotNull(installSource);
     }
 
     void removeInstallerPackage(String packageName) {
-        if (packageName == null) {
-            return;
-        }
-        if (packageName.equals(installerPackageName)) {
-            installerPackageName = null;
-            isOrphaned = true;
-        }
         installSource = installSource.removeInstallerPackage(packageName);
     }
 
+    public void setIsOrphaned(boolean isOrphaned) {
+        installSource = installSource.setIsOrphaned(isOrphaned);
+    }
+
     public void setVolumeUuid(String volumeUuid) {
         this.volumeUuid = volumeUuid;
     }
@@ -253,9 +242,7 @@
         cpuAbiOverrideString = orig.cpuAbiOverrideString;
         firstInstallTime = orig.firstInstallTime;
         installPermissionsFixed = orig.installPermissionsFixed;
-        installerPackageName = orig.installerPackageName;
         installSource = orig.installSource;
-        isOrphaned = orig.isOrphaned;
         keySetData = orig.keySetData;
         lastUpdateTime = orig.lastUpdateTime;
         legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
@@ -703,8 +690,7 @@
         this.signatures = other.signatures;
         this.installPermissionsFixed = other.installPermissionsFixed;
         this.keySetData = other.keySetData;
-        this.installerPackageName = other.installerPackageName;
-        this.isOrphaned = other.isOrphaned;
+        this.installSource = other.installSource;
         this.volumeUuid = other.volumeUuid;
         this.categoryHint = other.categoryHint;
         this.updateAvailable = other.updateAvailable;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5e209965..a11ae8c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2838,13 +2838,13 @@
         if (pkg.uidError) {
             serializer.attribute(null, "uidError", "true");
         }
-        if (pkg.installerPackageName != null) {
-            serializer.attribute(null, "installer", pkg.installerPackageName);
+        InstallSource installSource = pkg.installSource;
+        if (installSource.installerPackageName != null) {
+            serializer.attribute(null, "installer", installSource.installerPackageName);
         }
-        if (pkg.isOrphaned) {
+        if (installSource.isOrphaned) {
             serializer.attribute(null, "isOrphaned", "true");
         }
-        InstallSource installSource = pkg.installSource;
         if (installSource.initiatingPackageName != null) {
             serializer.attribute(null, "installInitiator", installSource.initiatingPackageName);
         }
@@ -3807,9 +3807,8 @@
         }
         if (packageSetting != null) {
             packageSetting.uidError = "true".equals(uidError);
-            packageSetting.installerPackageName = installerPackageName;
-            packageSetting.isOrphaned = "true".equals(isOrphaned);
-            packageSetting.installSource = InstallSource.create(installInitiatingPackageName);
+            packageSetting.installSource = InstallSource.create(
+                    installInitiatingPackageName, installerPackageName, "true".equals(isOrphaned));
             packageSetting.volumeUuid = volumeUuid;
             packageSetting.categoryHint = categoryHint;
             packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr;
@@ -4252,7 +4251,7 @@
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        return pkg.installerPackageName;
+        return pkg.installSource.installerPackageName;
     }
 
     boolean isOrphaned(String packageName) {
@@ -4260,7 +4259,7 @@
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        return pkg.isOrphaned;
+        return pkg.installSource.isOrphaned;
     }
 
     int getApplicationEnabledSettingLPr(String packageName, int userId) {
@@ -4313,8 +4312,9 @@
             pkgSetting.setStopped(stopped, userId);
             // pkgSetting.pkg.mSetStopped = stopped;
             if (pkgSetting.getNotLaunched(userId)) {
-                if (pkgSetting.installerPackageName != null) {
-                    pm.notifyFirstLaunch(pkgSetting.name, pkgSetting.installerPackageName, userId);
+                if (pkgSetting.installSource.installerPackageName != null) {
+                    pm.notifyFirstLaunch(pkgSetting.name,
+                            pkgSetting.installSource.installerPackageName, userId);
                 }
                 pkgSetting.setNotLaunched(false, userId);
             }
@@ -4477,7 +4477,8 @@
             pw.print(",");
             pw.print(ps.lastUpdateTime);
             pw.print(",");
-            pw.print(ps.installerPackageName != null ? ps.installerPackageName : "?");
+            pw.print(ps.installSource.installerPackageName != null
+                    ? ps.installSource.installerPackageName : "?");
             pw.println();
             if (ps.pkg != null) {
                 pw.print(checkinTag); pw.print("-"); pw.print("splt,");
@@ -4690,9 +4691,9 @@
         pw.print(prefix); pw.print("  lastUpdateTime=");
             date.setTime(ps.lastUpdateTime);
             pw.println(sdf.format(date));
-        if (ps.installerPackageName != null) {
+        if (ps.installSource.installerPackageName != null) {
             pw.print(prefix); pw.print("  installerPackageName=");
-                    pw.println(ps.installerPackageName);
+            pw.println(ps.installSource.installerPackageName);
         }
         if (ps.volumeUuid != null) {
             pw.print(prefix); pw.print("  volumeUuid=");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 95baa01..cfc5ca0 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -54,6 +54,7 @@
 import android.os.IBinder;
 import android.os.IProgressListener;
 import android.os.IUserManager;
+import android.os.IUserRestrictionsListener;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
@@ -1606,6 +1607,36 @@
         return false;
     }
 
+    @Override
+    public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
+            String value, int callingUid) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Non-system caller");
+        }
+        return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
+                value, callingUid);
+    }
+
+    @Override
+    public void addUserRestrictionsListener(final IUserRestrictionsListener listener) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Non-system caller");
+        }
+
+        // NOTE: unregistering not supported; only client is the settings provider,
+        // which installs a single static permanent listener.  If that listener goes
+        // bad it implies the whole system process is going to crash.
+        mLocalService.addUserRestrictionsListener(
+                (int userId, Bundle newRestrict, Bundle prevRestrict) -> {
+                    try {
+                        listener.onUserRestrictionsChanged(userId, newRestrict, prevRestrict);
+                    } catch (RemoteException re) {
+                        Slog.e("IUserRestrictionsListener",
+                                "Unable to invoke listener: " + re.getMessage());
+                    }
+                });
+    }
+
     /**
      * @hide
      *
@@ -2846,7 +2877,7 @@
                     return null;
                 }
                 // If we're adding a guest and there already exists one, bail.
-                if (isGuest && findCurrentGuestUser() != null) {
+                if (isGuest && !preCreate && findCurrentGuestUser() != null) {
                     Log.e(LOG_TAG, "Cannot add guest user. Guest user already exists.");
                     return null;
                 }
@@ -3100,7 +3131,8 @@
             final int size = mUsers.size();
             for (int i = 0; i < size; i++) {
                 final UserInfo user = mUsers.valueAt(i).info;
-                if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
+                if (user.isGuest() && !user.guestToRemove && !user.preCreated
+                        && !mRemovingUserIds.get(user.id)) {
                     return user;
                 }
             }
@@ -4410,7 +4442,7 @@
         @Override
         public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
                 String value, int callingUid) {
-            return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
+            return UserManagerService.this.isSettingRestrictedForUser(setting, userId,
                     value, callingUid);
         }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 5c65752..bb3388c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -4224,8 +4224,8 @@
         }
 
         @Override
-        public @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(
-                @PermissionInfo.Protection int protectionLevel) {
+        public @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection(
+                @PermissionInfo.Protection int protection) {
             ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
 
             synchronized (PermissionManagerService.this.mLock) {
@@ -4235,7 +4235,7 @@
                     BasePermission bp = mSettings.mPermissions.valueAt(i);
 
                     if (bp.perm != null && bp.perm.info != null
-                            && bp.protectionLevel == protectionLevel) {
+                            && bp.perm.info.getProtection() == protection) {
                         matchingPermissions.add(bp.perm.info);
                     }
                 }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 04ec5ba..a807a7e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -291,8 +291,8 @@
     public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
 
     /** Get all permission that have a certain protection level */
-    public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(
-            @PermissionInfo.Protection int protectionLevel);
+    public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtection(
+            @PermissionInfo.Protection int protection);
 
     /**
      * Returns the delegate used to influence permission checking.
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index df2b3ca..9b9f93f 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -48,12 +48,12 @@
 import android.permission.PermissionControllerManager;
 import android.provider.Telephony;
 import android.telecom.TelecomManager;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.LongSparseLongArray;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
-import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IAppOpsCallback;
@@ -67,6 +67,7 @@
 import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
 /**
@@ -144,7 +145,7 @@
         };
 
         final ArrayList<PermissionInfo> dangerousPerms =
-                permManagerInternal.getAllPermissionWithProtectionLevel(
+                permManagerInternal.getAllPermissionWithProtection(
                         PermissionInfo.PROTECTION_DANGEROUS);
 
         try {
@@ -389,8 +390,7 @@
         private final @NonNull PackageManager mPackageManager;
         private final @NonNull AppOpsManager mAppOpsManager;
 
-        /** All uid that need to be synchronized */
-        private final @NonNull SparseIntArray mAllUids = new SparseIntArray();
+        private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos;
 
         /**
          * All ops that need to be flipped to allow.
@@ -428,6 +428,18 @@
             mContext = context;
             mPackageManager = context.getPackageManager();
             mAppOpsManager = context.getSystemService(AppOpsManager.class);
+
+            mRuntimePermissionInfos = new ArrayMap<>();
+            PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
+                    PermissionManagerServiceInternal.class);
+            List<PermissionInfo> permissionInfos =
+                    permissionManagerInternal.getAllPermissionWithProtection(
+                            PermissionInfo.PROTECTION_DANGEROUS);
+            int permissionInfosSize = permissionInfos.size();
+            for (int i = 0; i < permissionInfosSize; i++) {
+                PermissionInfo permissionInfo = permissionInfos.get(i);
+                mRuntimePermissionInfos.put(permissionInfo.name, permissionInfo);
+            }
         }
 
         /**
@@ -489,7 +501,7 @@
          * Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
          */
         private void addAppOps(@NonNull PackageInfo packageInfo, @NonNull String permissionName) {
-            PermissionInfo permissionInfo = getPermissionInfo(permissionName);
+            PermissionInfo permissionInfo = mRuntimePermissionInfos.get(permissionName);
             if (permissionInfo == null) {
                 return;
             }
@@ -524,7 +536,7 @@
             boolean shouldGrantAppOp = shouldGrantAppOp(packageInfo, permissionInfo);
             if (shouldGrantAppOp) {
                 if (permissionInfo.backgroundPermission != null) {
-                    PermissionInfo backgroundPermissionInfo = getPermissionInfo(
+                    PermissionInfo backgroundPermissionInfo = mRuntimePermissionInfos.get(
                             permissionInfo.backgroundPermission);
                     boolean shouldGrantBackgroundAppOp = backgroundPermissionInfo != null
                             && shouldGrantAppOp(packageInfo, backgroundPermissionInfo);
@@ -551,15 +563,6 @@
             }
         }
 
-        @Nullable
-        private PermissionInfo getPermissionInfo(@NonNull String permissionName) {
-            try {
-                return mPackageManager.getPermissionInfo(permissionName, 0);
-            } catch (PackageManager.NameNotFoundException e) {
-                return null;
-            }
-        }
-
         private boolean shouldGrantAppOp(@NonNull PackageInfo packageInfo,
                 @NonNull PermissionInfo permissionInfo) {
             String permissionName = permissionInfo.name;
@@ -637,8 +640,6 @@
                 return;
             }
 
-            mAllUids.put(pkg.applicationInfo.uid, pkg.applicationInfo.uid);
-
             if (pkg.requestedPermissions == null) {
                 return;
             }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2593c38..5e1d93f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -386,6 +386,7 @@
     BurnInProtectionHelper mBurnInProtectionHelper;
     private DisplayFoldController mDisplayFoldController;
     AppOpsManager mAppOpsManager;
+    PackageManager mPackageManager;
     private boolean mHasFeatureAuto;
     private boolean mHasFeatureWatch;
     private boolean mHasFeatureLeanback;
@@ -1555,10 +1556,9 @@
     private void launchAllAppsAction() {
         Intent intent = new Intent(Intent.ACTION_ALL_APPS);
         if (mHasFeatureLeanback) {
-            final PackageManager pm = mContext.getPackageManager();
             Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
             intentLauncher.addCategory(Intent.CATEGORY_HOME);
-            ResolveInfo resolveInfo = pm.resolveActivityAsUser(intentLauncher,
+            ResolveInfo resolveInfo = mPackageManager.resolveActivityAsUser(intentLauncher,
                     PackageManager.MATCH_SYSTEM_ONLY,
                     mCurrentUserId);
             if (resolveInfo != null) {
@@ -1753,10 +1753,11 @@
         mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
-        mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
-        mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
-        mHasFeatureAuto = mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE);
-        mHasFeatureHdmiCec = mContext.getPackageManager().hasSystemFeature(FEATURE_HDMI_CEC);
+        mPackageManager = mContext.getPackageManager();
+        mHasFeatureWatch = mPackageManager.hasSystemFeature(FEATURE_WATCH);
+        mHasFeatureLeanback = mPackageManager.hasSystemFeature(FEATURE_LEANBACK);
+        mHasFeatureAuto = mPackageManager.hasSystemFeature(FEATURE_AUTOMOTIVE);
+        mHasFeatureHdmiCec = mPackageManager.hasSystemFeature(FEATURE_HDMI_CEC);
         mAccessibilityShortcutController =
                 new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
         mLogger = new MetricsLogger();
@@ -1994,7 +1995,7 @@
         }
 
         mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_NOTHING;
-        if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
+        if (mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
             mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
         }
     }
@@ -2138,7 +2139,7 @@
 
         ApplicationInfo appInfo;
         try {
-            appInfo = mContext.getPackageManager().getApplicationInfoAsUser(
+            appInfo = mPackageManager.getApplicationInfoAsUser(
                             attrs.packageName,
                             0 /* flags */,
                             UserHandle.getUserId(callingUid));
@@ -4914,7 +4915,7 @@
             @Override public void run() {
                 if (mBootMsgDialog == null) {
                     int theme;
-                    if (mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK)) {
+                    if (mPackageManager.hasSystemFeature(FEATURE_LEANBACK)) {
                         theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
                     } else {
                         theme = 0;
@@ -4943,7 +4944,7 @@
                             return true;
                         }
                     };
-                    if (mContext.getPackageManager().isDeviceUpgrading()) {
+                    if (mPackageManager.isDeviceUpgrading()) {
                         mBootMsgDialog.setTitle(R.string.android_upgrading_title);
                     } else {
                         mBootMsgDialog.setTitle(R.string.android_start_title);
@@ -5203,7 +5204,7 @@
         }
 
         ActivityInfo ai = null;
-        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
+        ResolveInfo info = mPackageManager.resolveActivityAsUser(
                 intent,
                 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
                 mCurrentUserId);
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index edf0cbf..b67d9b2 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -94,16 +94,16 @@
     private static final int MSG_PROFILE_TIMED_OUT = 5;
     private static final int MSG_WIRED_CHARGING_STARTED = 6;
 
-    private static final long[] WIRELESS_VIBRATION_TIME = {
+    private static final long[] CHARGING_VIBRATION_TIME = {
             40, 40, 40, 40, 40, 40, 40, 40, 40, // ramp-up sampling rate = 40ms
             40, 40, 40, 40, 40, 40, 40 // ramp-down sampling rate = 40ms
     };
-    private static final int[] WIRELESS_VIBRATION_AMPLITUDE = {
+    private static final int[] CHARGING_VIBRATION_AMPLITUDE = {
             1, 4, 11, 25, 44, 67, 91, 114, 123, // ramp-up amplitude (from 0 to 50%)
             103, 79, 55, 34, 17, 7, 2 // ramp-up amplitude
     };
-    private static final VibrationEffect WIRELESS_CHARGING_VIBRATION_EFFECT =
-            VibrationEffect.createWaveform(WIRELESS_VIBRATION_TIME, WIRELESS_VIBRATION_AMPLITUDE,
+    private static final VibrationEffect CHARGING_VIBRATION_EFFECT =
+            VibrationEffect.createWaveform(CHARGING_VIBRATION_TIME, CHARGING_VIBRATION_AMPLITUDE,
                     -1);
     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -130,6 +130,10 @@
     // True if the device should suspend when the screen is off due to proximity.
     private final boolean mSuspendWhenScreenOffDueToProximityConfig;
 
+    // True if the device should show the wireless charging animation when the device
+    // begins charging wirelessly
+    private final boolean mShowWirelessChargingAnimationConfig;
+
     // The current interactive state.  This is set as soon as an interactive state
     // transition begins so as to capture the reason that it happened.  At some point
     // this state will propagate to the pending state then eventually to the
@@ -182,6 +186,8 @@
 
         mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
+        mShowWirelessChargingAnimationConfig = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim);
 
         // Initialize interactive state for battery stats.
         try {
@@ -755,35 +761,45 @@
         }
     };
 
-    /**
-     * If enabled, plays a sound and/or vibration when wireless or non-wireless charging has started
-     */
-    private void playChargingStartedFeedback(@UserIdInt int userId) {
-        playChargingStartedVibration(userId);
+    private void playChargingStartedFeedback(@UserIdInt int userId, boolean wireless) {
+        if (!isChargingFeedbackEnabled(userId)) {
+            return;
+        }
+
+        // vibrate
+        final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
+        if (vibrate) {
+            mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, VIBRATION_ATTRIBUTES);
+        }
+
+        // play sound
         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
-                Settings.Global.CHARGING_STARTED_SOUND);
-        if (isChargingFeedbackEnabled(userId) && soundPath != null) {
-            final Uri soundUri = Uri.parse("file://" + soundPath);
-            if (soundUri != null) {
-                final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                if (sfx != null) {
-                    sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                    sfx.play();
-                }
+                wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND
+                        : Settings.Global.CHARGING_STARTED_SOUND);
+        final Uri soundUri = Uri.parse("file://" + soundPath);
+        if (soundUri != null) {
+            final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+            if (sfx != null) {
+                sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                sfx.play();
             }
         }
     }
 
     private void showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
-        playChargingStartedFeedback(userId);
-        if (mStatusBarManagerInternal != null) {
+        // play sounds + haptics
+        playChargingStartedFeedback(userId, true /* wireless */);
+
+        // show animation
+        if (mShowWirelessChargingAnimationConfig && mStatusBarManagerInternal != null) {
             mStatusBarManagerInternal.showChargingAnimation(batteryLevel);
         }
         mSuspendBlocker.release();
     }
 
     private void showWiredChargingStarted(@UserIdInt int userId) {
-        playChargingStartedFeedback(userId);
+        playChargingStartedFeedback(userId, false /* wireless */);
         mSuspendBlocker.release();
     }
 
@@ -791,14 +807,6 @@
         mTrustManager.setDeviceLockedForUser(userId, true /*locked*/);
     }
 
-    private void playChargingStartedVibration(@UserIdInt int userId) {
-        final boolean vibrateEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
-        if (vibrateEnabled && isChargingFeedbackEnabled(userId)) {
-            mVibrator.vibrate(WIRELESS_CHARGING_VIBRATION_EFFECT, VIBRATION_ATTRIBUTES);
-        }
-    }
-
     private boolean isChargingFeedbackEnabled(@UserIdInt int userId) {
         final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.CHARGING_SOUNDS_ENABLED, 1, userId) != 0;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index eb648b3..befe4e9 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -548,12 +548,16 @@
 
     private final class ForegroundProfileObserver extends SynchronousUserSwitchObserver {
         @Override
-        public void onUserSwitching(int newUserId) throws RemoteException {}
+        public void onUserSwitching(@UserIdInt int newUserId) throws RemoteException {
+            synchronized (mLock) {
+                mUserId = newUserId;
+            }
+        }
 
         @Override
         public void onForegroundProfileSwitch(@UserIdInt int newProfileId) throws RemoteException {
             final long now = SystemClock.uptimeMillis();
-            synchronized(mLock) {
+            synchronized (mLock) {
                 mForegroundProfile = newProfileId;
                 maybeUpdateForegroundProfileLastActivityLocked(now);
             }
@@ -562,6 +566,8 @@
 
     // User id corresponding to activity the user is currently interacting with.
     private @UserIdInt int mForegroundProfile;
+    // User id of main profile for the current user (doesn't include managed profiles)
+    private @UserIdInt int mUserId;
 
     // Per-profile state to track when a profile should be locked.
     private final SparseArray<ProfilePowerState> mProfilePowerState = new SparseArray<>();
@@ -1792,9 +1798,9 @@
                 if (mBootCompleted) {
                     if (mIsPowered && !BatteryManager.isPlugWired(oldPlugType)
                             && BatteryManager.isPlugWired(mPlugType)) {
-                        mNotifier.onWiredChargingStarted(mForegroundProfile);
+                        mNotifier.onWiredChargingStarted(mUserId);
                     } else if (dockedOnWirelessCharger) {
-                        mNotifier.onWirelessChargingStarted(mBatteryLevel, mForegroundProfile);
+                        mNotifier.onWirelessChargingStarted(mBatteryLevel, mUserId);
                     }
                 }
             }
@@ -3493,6 +3499,7 @@
             pw.println("  mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
             pw.println("  mIsVrModeEnabled=" + mIsVrModeEnabled);
             pw.println("  mForegroundProfile=" + mForegroundProfile);
+            pw.println("  mUserId=" + mUserId);
 
             final long sleepTimeout = getSleepTimeoutLocked();
             final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
diff --git a/services/core/java/com/android/server/protolog/ProtoLogImpl.java b/services/core/java/com/android/server/protolog/ProtoLogImpl.java
index 20bab55..1653b3d 100644
--- a/services/core/java/com/android/server/protolog/ProtoLogImpl.java
+++ b/services/core/java/com/android/server/protolog/ProtoLogImpl.java
@@ -45,7 +45,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.IllegalFormatConversionException;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
@@ -57,8 +56,18 @@
 public class ProtoLogImpl {
     private static final TreeMap<String, IProtoLogGroup> LOG_GROUPS = new TreeMap<>();
 
+    /**
+     * A runnable to update the cached output of {@link #isEnabled}.
+     *
+     * Must be invoked after every action that could change the result of {@link #isEnabled}, eg.
+     * starting / stopping proto log, or enabling / disabling log groups.
+     */
+    static Runnable sCacheUpdater = () -> { };
+
     private static void addLogGroupEnum(IProtoLogGroup[] config) {
-        Arrays.stream(config).forEach(group -> LOG_GROUPS.put(group.name(), group));
+        for (IProtoLogGroup group : config) {
+            LOG_GROUPS.put(group.name(), group);
+        }
     }
 
     static {
@@ -112,7 +121,7 @@
 
     /** Returns true iff logging is enabled for the given {@code IProtoLogGroup}. */
     public static boolean isEnabled(IProtoLogGroup group) {
-        return group.isLogToProto()
+        return group.isLogToLogcat()
                 || (group.isLogToProto() && getSingleInstance().isProtoEnabled());
     }
 
@@ -303,6 +312,7 @@
             mProtoLogEnabled = true;
             mProtoLogEnabledLockFree = true;
         }
+        sCacheUpdater.run();
     }
 
     /**
@@ -327,6 +337,7 @@
                 throw new IllegalStateException("logging enabled while waiting for flush.");
             }
         }
+        sCacheUpdater.run();
     }
 
     /**
@@ -351,6 +362,7 @@
                 return -1;
             }
         }
+        sCacheUpdater.run();
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 1cf07cb..8b79c3f 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -21,6 +21,7 @@
 import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -33,7 +34,9 @@
 import android.content.rollback.RollbackManager;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 import android.os.UserManager;
+import android.text.TextUtils;
 import android.util.IntArray;
 import android.util.Slog;
 import android.util.SparseLongArray;
@@ -142,18 +145,37 @@
     private final Object mLock = new Object();
 
     /**
+     * The user that performed the install with rollback enabled.
+     */
+    public final int mUserId;
+
+    /**
+     * The installer package name from the install session that enabled the rollback. May be null if
+     * that session did not set this value.
+     *
+     * If this is an empty string then the installer package name will be resolved by
+     * PackageManager.
+     */
+    @Nullable public final String mInstallerPackageName;
+
+    /**
      * Constructs a new, empty Rollback instance.
      *
      * @param rollbackId the id of the rollback.
      * @param backupDir the directory where the rollback data is stored.
      * @param stagedSessionId the session id if this is a staged rollback, -1 otherwise.
+     * @param userId the user that performed the install with rollback enabled.
+     * @param installerPackageName the installer package name from the original install session.
      */
-    Rollback(int rollbackId, File backupDir, int stagedSessionId) {
+    Rollback(int rollbackId, File backupDir, int stagedSessionId, int userId,
+            String installerPackageName) {
         this.info = new RollbackInfo(rollbackId,
                 /* packages */ new ArrayList<>(),
                 /* isStaged */ stagedSessionId != -1,
                 /* causePackages */ new ArrayList<>(),
                 /* committedSessionId */ -1);
+        mUserId = userId;
+        mInstallerPackageName = installerPackageName;
         mBackupDir = backupDir;
         mStagedSessionId = stagedSessionId;
         mState = ROLLBACK_STATE_ENABLING;
@@ -164,8 +186,11 @@
      * Constructs a pre-populated Rollback instance.
      */
     Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
-            @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) {
+            @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress,
+            int userId, String installerPackageName) {
         this.info = info;
+        mUserId = userId;
+        mInstallerPackageName = installerPackageName;
         mBackupDir = backupDir;
         mTimestamp = timestamp;
         mStagedSessionId = stagedSessionId;
@@ -216,6 +241,21 @@
     }
 
     /**
+     * Returns the ID of the user that performed the install with rollback enabled.
+     */
+    int getUserId() {
+        return mUserId;
+    }
+
+    /**
+     * Returns the installer package name from the install session that enabled the rollback. In the
+     * case that this is called on a rollback from an older version, returns the empty string.
+     */
+    @Nullable String getInstallerPackageName() {
+        return mInstallerPackageName;
+    }
+
+    /**
      * Returns true if the rollback is in the ENABLING state.
      */
     boolean isEnabling() {
@@ -360,7 +400,8 @@
             // Get a context to use to install the downgraded version of the package.
             Context pkgContext;
             try {
-                pkgContext = context.createPackageContext(callerPackageName, 0);
+                pkgContext = context.createPackageContextAsUser(callerPackageName, 0,
+                        UserHandle.of(mUserId));
             } catch (PackageManager.NameNotFoundException e) {
                 sendFailure(context, statusReceiver, RollbackManager.STATUS_FAILURE,
                         "Invalid callerPackageName");
@@ -385,15 +426,13 @@
                 for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
                     PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                             PackageInstaller.SessionParams.MODE_FULL_INSTALL);
-                    // TODO: We can't get the installerPackageName for apex
-                    // (b/123920130). Is it okay to ignore the installer package
-                    // for apex?
-                    if (!pkgRollbackInfo.isApex()) {
-                        String installerPackageName =
-                                pm.getInstallerPackageName(pkgRollbackInfo.getPackageName());
-                        if (installerPackageName != null) {
-                            params.setInstallerPackageName(installerPackageName);
-                        }
+                    String installerPackageName = mInstallerPackageName;
+                    if (TextUtils.isEmpty(mInstallerPackageName)) {
+                        installerPackageName = pm.getInstallerPackageName(
+                                pkgRollbackInfo.getPackageName());
+                    }
+                    if (installerPackageName != null) {
+                        params.setInstallerPackageName(installerPackageName);
                     }
                     params.setRequestDowngrade(true);
                     params.setRequiredInstalledVersionCode(
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index cd44f64..ef4c12e 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1248,13 +1248,22 @@
     @GuardedBy("mLock")
     private NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) {
         int rollbackId = allocateRollbackIdLocked();
+        final int userId;
+        if (parentSession.getUser() == UserHandle.ALL) {
+            userId = UserHandle.USER_SYSTEM;
+        } else {
+            userId = parentSession.getUser().getIdentifier();
+        }
+        String installerPackageName = parentSession.getInstallerPackageName();
         final Rollback rollback;
         int parentSessionId = parentSession.getSessionId();
 
         if (parentSession.isStaged()) {
-            rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
+            rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId, userId,
+                    installerPackageName);
         } else {
-            rollback = mRollbackStore.createNonStagedRollback(rollbackId);
+            rollback = mRollbackStore.createNonStagedRollback(rollbackId, userId,
+                    installerPackageName);
         }
 
         int[] packageSessionIds;
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 425da37..550c754 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -16,6 +16,8 @@
 
 package com.android.server.rollback;
 
+import static android.os.UserHandle.USER_SYSTEM;
+
 import static com.android.server.rollback.Rollback.rollbackStateFromString;
 
 import android.annotation.NonNull;
@@ -196,18 +198,19 @@
      * Creates a new Rollback instance for a non-staged rollback with
      * backupDir assigned.
      */
-    Rollback createNonStagedRollback(int rollbackId) {
+    Rollback createNonStagedRollback(int rollbackId, int userId, String installerPackageName) {
         File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
-        return new Rollback(rollbackId, backupDir, -1);
+        return new Rollback(rollbackId, backupDir, -1, userId, installerPackageName);
     }
 
     /**
      * Creates a new Rollback instance for a staged rollback with
      * backupDir assigned.
      */
-    Rollback createStagedRollback(int rollbackId, int stagedSessionId) {
+    Rollback createStagedRollback(int rollbackId, int stagedSessionId, int userId,
+            String installerPackageName) {
         File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
-        return new Rollback(rollbackId, backupDir, stagedSessionId);
+        return new Rollback(rollbackId, backupDir, stagedSessionId, userId, installerPackageName);
     }
 
     /**
@@ -263,6 +266,8 @@
             dataJson.put("state", rollback.getStateAsString());
             dataJson.put("apkSessionId", rollback.getApkSessionId());
             dataJson.put("restoreUserDataInProgress", rollback.isRestoreUserDataInProgress());
+            dataJson.put("userId", rollback.getUserId());
+            dataJson.putOpt("installerPackageName", rollback.getInstallerPackageName());
 
             PrintWriter pw = new PrintWriter(new File(rollback.getBackupDir(), "rollback.json"));
             pw.println(dataJson.toString());
@@ -305,7 +310,9 @@
                 dataJson.getInt("stagedSessionId"),
                 rollbackStateFromString(dataJson.getString("state")),
                 dataJson.getInt("apkSessionId"),
-                dataJson.getBoolean("restoreUserDataInProgress"));
+                dataJson.getBoolean("restoreUserDataInProgress"),
+                dataJson.optInt("userId", USER_SYSTEM),
+                dataJson.optString("installerPackageName", ""));
     }
 
     private static JSONObject toJson(VersionedPackage pkg) throws JSONException {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index a93d2b8..ec64ee6 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -18,7 +18,10 @@
 
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.view.InsetsState.InternalInsetType;
+import android.view.WindowInsetsController.Appearance;
 
+import com.android.internal.view.AppearanceRegion;
 import com.android.server.notification.NotificationDelegate;
 
 public interface StatusBarManagerInternal {
@@ -75,7 +78,7 @@
 
     void startAssist(Bundle args);
     void onCameraLaunchGestureDetected(int source);
-    void topAppWindowChanged(int displayId, boolean menuVisible);
+    void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
     void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
             int mask, Rect fullscreenBounds, Rect dockedBounds, boolean isNavbarColorManagedByIme,
             String cause);
@@ -113,4 +116,14 @@
      * Notifies System UI whether the recents animation is running.
      */
     void onRecentsAnimationStateChanged(boolean running);
+
+    /** @see com.android.internal.statusbar.IStatusBar#onSystemBarAppearanceChanged */
+    void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+            AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme);
+
+    /** @see com.android.internal.statusbar.IStatusBar#showTransient */
+    void showTransient(int displayId, @InternalInsetType int[] types);
+
+    /** @see com.android.internal.statusbar.IStatusBar#abortTransient */
+    void abortTransient(int displayId, @InternalInsetType int[] types);
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 65bb2342..489c343 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -47,6 +47,7 @@
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.WindowInsetsController.Appearance;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -56,6 +57,7 @@
 import com.android.internal.statusbar.RegisterStatusBarResult;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.view.AppearanceRegion;
 import com.android.server.LocalServices;
 import com.android.server.notification.NotificationDelegate;
 import com.android.server.policy.GlobalActionsProvider;
@@ -256,8 +258,8 @@
         }
 
         @Override
-        public void topAppWindowChanged(int displayId, boolean menuVisible) {
-            StatusBarManagerService.this.topAppWindowChanged(displayId, menuVisible);
+        public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
+            StatusBarManagerService.this.topAppWindowChanged(displayId, isFullscreen, isImmersive);
         }
 
         @Override
@@ -467,6 +469,36 @@
             }
 
         }
+
+        @Override
+        public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
+                AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+            // TODO (b/118118435): save the information to UiState
+            if (mBar != null) {
+                try {
+                    mBar.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
+                            navbarColorManagedByIme);
+                } catch (RemoteException ex) { }
+            }
+        }
+
+        @Override
+        public void showTransient(int displayId, int[] types) {
+            if (mBar != null) {
+                try {
+                    mBar.showTransient(displayId, types);
+                } catch (RemoteException ex) { }
+            }
+        }
+
+        @Override
+        public void abortTransient(int displayId, int[] types) {
+            if (mBar != null) {
+                try {
+                    mBar.abortTransient(displayId, types);
+                } catch (RemoteException ex) { }
+            }
+        }
     };
 
     private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {
@@ -623,11 +655,11 @@
     }
 
     @Override
-    public void onBiometricAuthenticated(boolean authenticated, String failureReason) {
+    public void onBiometricAuthenticated() {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.onBiometricAuthenticated(authenticated, failureReason);
+                mBar.onBiometricAuthenticated();
             } catch (RemoteException ex) {
             }
         }
@@ -645,11 +677,11 @@
     }
 
     @Override
-    public void onBiometricError(int errorCode, String error) {
+    public void onBiometricError(int modality, int error, int vendorCode) {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.onBiometricError(errorCode, error);
+                mBar.onBiometricError(modality, error, vendorCode);
             } catch (RemoteException ex) {
             }
         }
@@ -817,23 +849,19 @@
     }
 
     /**
-     * Hide or show the on-screen Menu key. Only call this from the window manager, typically in
-     * response to a window with {@link android.view.WindowManager.LayoutParams#needsMenuKey} set
-     * to {@link android.view.WindowManager.LayoutParams#NEEDS_MENU_SET_TRUE}.
+     * Enables System UI to know whether the top app is fullscreen or not, and whether this app is
+     * in immersive mode or not.
      */
-    private void topAppWindowChanged(int displayId, final boolean menuVisible) {
+    private void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
         enforceStatusBar();
 
-        if (SPEW) {
-            Slog.d(TAG, "display#" + displayId + ": "
-                    + (menuVisible ? "showing" : "hiding") + " MENU key");
-        }
         synchronized(mLock) {
-            getUiState(displayId).setMenuVisible(menuVisible);
+            getUiState(displayId).setFullscreen(isFullscreen);
+            getUiState(displayId).setImmersive(isImmersive);
             mHandler.post(() -> {
                 if (mBar != null) {
                     try {
-                        mBar.topAppWindowChanged(displayId, menuVisible);
+                        mBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
                     } catch (RemoteException ex) {
                     }
                 }
@@ -942,7 +970,8 @@
         private int mDockedStackSysUiVisibility = 0;
         private final Rect mFullscreenStackBounds = new Rect();
         private final Rect mDockedStackBounds = new Rect();
-        private boolean mMenuVisible = false;
+        private boolean mFullscreen = false;
+        private boolean mImmersive = false;
         private int mDisabled1 = 0;
         private int mDisabled2 = 0;
         private int mImeWindowVis = 0;
@@ -964,12 +993,12 @@
             mDisabled2 = disabled2;
         }
 
-        private boolean isMenuVisible() {
-            return mMenuVisible;
+        private void setFullscreen(boolean isFullscreen) {
+            mFullscreen = isFullscreen;
         }
 
-        private void setMenuVisible(boolean menuVisible) {
-            mMenuVisible = menuVisible;
+        private void setImmersive(boolean immersive) {
+            mImmersive = immersive;
         }
 
         private boolean disableEquals(int disabled1, int disabled2) {
@@ -1056,12 +1085,12 @@
             // Make it aware of multi-display if needed.
             final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
             return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
-                    state.mSystemUiVisibility, state.mMenuVisible, state.mImeWindowVis,
+                    state.mSystemUiVisibility, state.mImeWindowVis,
                     state.mImeBackDisposition, state.mShowImeSwitcher,
                     gatherDisableActionsLocked(mCurrentUserId, 2),
                     state.mFullscreenStackSysUiVisibility, state.mDockedStackSysUiVisibility,
                     state.mImeToken, state.mFullscreenStackBounds, state.mDockedStackBounds,
-                    state.mNavbarColorManagedByIme);
+                    state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive);
         }
     }
 
diff --git a/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java
index 7bdc8a3..9dbbf16 100644
--- a/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/SimpleTimeDetectorStrategy.java
@@ -19,7 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
-import android.app.timedetector.TimeSignal;
+import android.app.timedetector.PhoneTimeSuggestion;
 import android.content.Intent;
 import android.util.Slog;
 import android.util.TimestampedValue;
@@ -48,9 +48,8 @@
     // @NonNull after initialize()
     private Callback mCallback;
 
-    // NITZ state.
-    @Nullable private TimestampedValue<Long> mLastNitzTime;
-
+    // Last phone suggestion.
+    @Nullable private PhoneTimeSuggestion mLastPhoneSuggestion;
 
     // Information about the last time signal received: Used when toggling auto-time.
     @Nullable private TimestampedValue<Long> mLastSystemClockTime;
@@ -65,46 +64,40 @@
     }
 
     @Override
-    public void suggestTime(@NonNull TimeSignal timeSignal) {
-        if (!TimeSignal.SOURCE_ID_NITZ.equals(timeSignal.getSourceId())) {
-            Slog.w(TAG, "Ignoring signal from unsupported source: " + timeSignal);
-            return;
-        }
-
+    public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion) {
         // NITZ logic
 
-        TimestampedValue<Long> newNitzUtcTime = timeSignal.getUtcTime();
-        boolean nitzTimeIsValid = validateNewNitzTime(newNitzUtcTime, mLastNitzTime);
-        if (!nitzTimeIsValid) {
+        boolean timeSuggestionIsValid =
+                validateNewPhoneSuggestion(timeSuggestion, mLastPhoneSuggestion);
+        if (!timeSuggestionIsValid) {
             return;
         }
         // Always store the last NITZ value received, regardless of whether we go on to use it to
         // update the system clock. This is so that we can validate future NITZ signals.
-        mLastNitzTime = newNitzUtcTime;
+        mLastPhoneSuggestion = timeSuggestion;
 
         // System clock update logic.
 
         // Historically, Android has sent a telephony broadcast only when setting the time using
         // NITZ.
-        final boolean sendNetworkBroadcast =
-                TimeSignal.SOURCE_ID_NITZ.equals(timeSignal.getSourceId());
+        final boolean sendNetworkBroadcast = true;
 
-        final TimestampedValue<Long> newUtcTime = newNitzUtcTime;
+        final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
         setSystemClockIfRequired(newUtcTime, sendNetworkBroadcast);
     }
 
-    private static boolean validateNewNitzTime(TimestampedValue<Long> newNitzUtcTime,
-            TimestampedValue<Long> lastNitzTime) {
+    private static boolean validateNewPhoneSuggestion(@NonNull PhoneTimeSuggestion newSuggestion,
+            @Nullable PhoneTimeSuggestion lastSuggestion) {
 
-        if (lastNitzTime != null) {
-            long referenceTimeDifference =
-                    TimestampedValue.referenceTimeDifference(newNitzUtcTime, lastNitzTime);
+        if (lastSuggestion != null) {
+            long referenceTimeDifference = TimestampedValue.referenceTimeDifference(
+                    newSuggestion.getUtcTime(), lastSuggestion.getUtcTime());
             if (referenceTimeDifference < 0 || referenceTimeDifference > Integer.MAX_VALUE) {
                 // Out of order or bogus.
                 Slog.w(TAG, "validateNewNitzTime: Bad NITZ signal received."
                         + " referenceTimeDifference=" + referenceTimeDifference
-                        + " lastNitzTime=" + lastNitzTime
-                        + " newNitzUtcTime=" + newNitzUtcTime);
+                        + " lastSuggestion=" + lastSuggestion
+                        + " newSuggestion=" + newSuggestion);
                 return false;
             }
         }
@@ -182,7 +175,7 @@
 
     @Override
     public void dump(@NonNull PrintWriter pw, @Nullable String[] args) {
-        pw.println("mLastNitzTime=" + mLastNitzTime);
+        pw.println("mLastPhoneSuggestion=" + mLastPhoneSuggestion);
         pw.println("mLastSystemClockTimeSet=" + mLastSystemClockTimeSet);
         pw.println("mLastSystemClockTime=" + mLastSystemClockTime);
         pw.println("mLastSystemClockTimeSendNetworkBroadcast="
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 9c83000..ee42279 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -19,7 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.timedetector.ITimeDetectorService;
-import android.app.timedetector.TimeSignal;
+import android.app.timedetector.PhoneTimeSuggestion;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -96,14 +96,14 @@
     }
 
     @Override
-    public void suggestTime(@NonNull TimeSignal timeSignal) {
+    public void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSignal) {
         enforceSetTimePermission();
         Objects.requireNonNull(timeSignal);
 
         long idToken = Binder.clearCallingIdentity();
         try {
             synchronized (mStrategyLock) {
-                mTimeDetectorStrategy.suggestTime(timeSignal);
+                mTimeDetectorStrategy.suggestPhoneTime(timeSignal);
             }
         } finally {
             Binder.restoreCallingIdentity(idToken);
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index e050865..7c2a945 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -18,7 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.timedetector.TimeSignal;
+import android.app.timedetector.PhoneTimeSuggestion;
 import android.content.Intent;
 import android.util.TimestampedValue;
 
@@ -72,7 +72,7 @@
     void initialize(@NonNull Callback callback);
 
     /** Process the suggested time. */
-    void suggestTime(@NonNull TimeSignal timeSignal);
+    void suggestPhoneTime(@NonNull PhoneTimeSuggestion timeSuggestion);
 
     /** Handle the auto-time setting being toggled on or off. */
     void handleAutoTimeDetectionToggle(boolean enabled);
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index e4cb19e..e72ba8d 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -17,6 +17,7 @@
 package com.android.server.twilight;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -160,8 +161,13 @@
         // Request the device's location immediately if a previous location isn't available.
         if (mLocationManager.getLastLocation() == null) {
             if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
-                mLocationManager.requestSingleUpdate(
-                        LocationManager.NETWORK_PROVIDER, this, Looper.getMainLooper());
+                mLocationManager.getCurrentLocation(
+                        LocationManager.NETWORK_PROVIDER, null, getContext().getMainExecutor(),
+                        this::onLocationChanged);
+            } else if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
+                mLocationManager.getCurrentLocation(
+                        LocationManager.GPS_PROVIDER, null, getContext().getMainExecutor(),
+                        this::onLocationChanged);
             }
         }
 
@@ -218,12 +224,7 @@
                 for (int i = mListeners.size() - 1; i >= 0; --i) {
                     final TwilightListener listener = mListeners.keyAt(i);
                     final Handler handler = mListeners.valueAt(i);
-                    handler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            listener.onTwilightStateChanged(state);
-                        }
-                    });
+                    handler.post(() -> listener.onTwilightStateChanged(state));
                 }
             }
         }
@@ -243,12 +244,8 @@
     }
 
     @Override
-    public void onLocationChanged(Location location) {
-        // Location providers may erroneously return (0.0, 0.0) when they fail to determine the
-        // device's location. These location updates can be safely ignored since the chance of a
-        // user actually being at these coordinates is quite low.
-        if (location != null
-                && !(location.getLongitude() == 0.0 && location.getLatitude() == 0.0)) {
+    public void onLocationChanged(@Nullable Location location) {
+        if (location != null) {
             Slog.d(TAG, "onLocationChanged:"
                     + " provider=" + location.getProvider()
                     + " accuracy=" + location.getAccuracy()
diff --git a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
new file mode 100644
index 0000000..852f707
--- /dev/null
+++ b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
@@ -0,0 +1,39 @@
+/*
+ * 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.updates;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.Slog;
+
+/**
+ * Emergency Number Database Install Receiver.
+ */
+public class EmergencyNumberDbInstallReceiver extends ConfigUpdateInstallReceiver {
+
+    private static final String TAG = "EmergencyNumberDbInstallReceiver";
+
+    public EmergencyNumberDbInstallReceiver() {
+        super("/data/misc/emergencynumberdb", "emergency_number_db", "metadata/", "version");
+    }
+
+    @Override
+    protected void postInstall(Context context, Intent intent) {
+        Slog.i(TAG, "Emergency number database is updated in file partition");
+        // TODO Send a notification to EmergencyNumberTracker for updating of emergency number db.
+    }
+}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3cdb59b..3663f46 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1228,6 +1228,7 @@
                         saveSettingsLocked(mWallpaper.userId);
                     }
                     FgThread.getHandler().removeCallbacks(mResetRunnable);
+                    mContext.getMainThreadHandler().removeCallbacks(this::tryToRebind);
                 }
             }
         }
@@ -1270,6 +1271,34 @@
             }
         }
 
+        private void tryToRebind() {
+            synchronized (mLock) {
+                if (mWallpaper.wallpaperUpdating) {
+                    return;
+                }
+                final ComponentName wpService = mWallpaper.wallpaperComponent;
+                // The broadcast of package update could be delayed after service disconnected. Try
+                // to re-bind the service for 10 seconds.
+                if (bindWallpaperComponentLocked(
+                        wpService, true, false, mWallpaper, null)) {
+                    mWallpaper.connection.scheduleTimeoutLocked();
+                } else if (SystemClock.uptimeMillis() - mWallpaper.lastDiedTime
+                        < WALLPAPER_RECONNECT_TIMEOUT_MS) {
+                    // Bind fail without timeout, schedule rebind
+                    Slog.w(TAG, "Rebind fail! Try again later");
+                    mContext.getMainThreadHandler().postDelayed(this::tryToRebind, 1000);
+                } else {
+                    // Timeout
+                    Slog.w(TAG, "Reverting to built-in wallpaper!");
+                    clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
+                    final String flattened = wpService.flattenToString();
+                    EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
+                            flattened.substring(0, Math.min(flattened.length(),
+                                    MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
+                }
+            }
+        }
+
         private void processDisconnect(final ServiceConnection connection) {
             synchronized (mLock) {
                 // The wallpaper disappeared.  If this isn't a system-default one, track
@@ -1293,20 +1322,8 @@
                             clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
                         } else {
                             mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
-
-                            clearWallpaperComponentLocked(mWallpaper);
-                            if (bindWallpaperComponentLocked(
-                                    wpService, false, false, mWallpaper, null)) {
-                                mWallpaper.connection.scheduleTimeoutLocked();
-                            } else {
-                                Slog.w(TAG, "Reverting to built-in wallpaper!");
-                                clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
-                            }
+                            tryToRebind();
                         }
-                        final String flattened = wpService.flattenToString();
-                        EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
-                                flattened.substring(0, Math.min(flattened.length(),
-                                        MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
                     }
                 } else {
                     if (DEBUG_LIVE) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 10415f5..5e4f75c 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -116,6 +116,14 @@
         return result;
     }
 
+    /**
+     * Sets a callback for observing which windows are touchable for the purposes
+     * of accessibility on specified display.
+     *
+     * @param displayId The logical display id.
+     * @param callback The callback.
+     * @return {@code false} if display id is not valid or an embedded display.
+     */
     public boolean setWindowsForAccessibilityCallbackLocked(int displayId,
             WindowsForAccessibilityCallback callback) {
         if (callback != null) {
@@ -129,7 +137,7 @@
                 if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) {
                     // The window observer of this embedded display had been set from
                     // window manager after setting its parent window.
-                    return true;
+                    return false;
                 } else {
                     throw new IllegalStateException(
                             "Windows for accessibility callback of display "
@@ -725,7 +733,7 @@
             }
 
             private Region getLetterboxBounds(WindowState windowState) {
-                final AppWindowToken appToken = windowState.mAppToken;
+                final ActivityRecord appToken = windowState.mActivityRecord;
                 if (appToken == null) {
                     return new Region();
                 }
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 673366f..48a7b73 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1294,14 +1294,14 @@
         if (mDisplayContent == null) {
             return;
         }
-        final AppWindowToken newFocus;
+        final ActivityRecord newFocus;
         final IBinder token = r.appToken;
         if (token == null) {
             ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Clearing focused app, displayId=%d",
                     mDisplayId);
             newFocus = null;
         } else {
-            newFocus = mService.mWindowManager.mRoot.getAppWindowToken(token);
+            newFocus = mService.mWindowManager.mRoot.getActivityRecord(token);
             if (newFocus == null) {
                 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
                         + ", displayId=" + mDisplayId);
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index e6c6b12e..9d41d97 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -187,9 +187,22 @@
         private int startingWindowDelayMs = INVALID_DELAY;
         private int bindApplicationDelayMs = INVALID_DELAY;
         private int reason = APP_TRANSITION_TIMEOUT;
-        private boolean loggedWindowsDrawn;
+        // TODO(b/132736359) The number may need to consider the visibility change.
+        private int numUndrawnActivities = 1;
         private boolean loggedStartingWindowDrawn;
         private boolean launchTraceActive;
+
+        /**
+         * Remembers the latest launched activity to represent the final transition. This also
+         * increments the number of activities that should be drawn, so a consecutive launching
+         * sequence can be coalesced as one event.
+         */
+        void setLatestLaunchedActivity(ActivityRecord r) {
+            if (launchedActivity == r) {
+                return;
+            }
+            launchedActivity = r;
+        }
     }
 
     final class WindowingModeTransitionInfoSnapshot {
@@ -400,7 +413,7 @@
             // the other attributes.
 
             // Coalesce multiple (trampoline) activities from a single sequence together.
-            info.launchedActivity = launchedActivity;
+            info.setLatestLaunchedActivity(launchedActivity);
             return;
         }
 
@@ -422,7 +435,7 @@
         // A new launch sequence [with the windowingMode] has begun.
         // Start tracking it.
         final WindowingModeTransitionInfo newInfo = new WindowingModeTransitionInfo();
-        newInfo.launchedActivity = launchedActivity;
+        newInfo.setLatestLaunchedActivity(launchedActivity);
         newInfo.currentTransitionProcessRunning = processRunning;
         newInfo.startResult = resultCode;
         mWindowingModeTransitionInfo.put(windowingMode, newInfo);
@@ -448,11 +461,11 @@
         if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
 
         final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
-        if (info == null || info.loggedWindowsDrawn) {
+        if (info == null || info.numUndrawnActivities == 0) {
             return null;
         }
         info.windowsDrawnDelayMs = calculateDelay(timestampNs);
-        info.loggedWindowsDrawn = true;
+        info.numUndrawnActivities--;
         final WindowingModeTransitionInfoSnapshot infoSnapshot =
                 new WindowingModeTransitionInfoSnapshot(info);
         if (allWindowsDrawn() && mLoggedTransitionStarting) {
@@ -594,9 +607,10 @@
         }
     }
 
-    private boolean allWindowsDrawn() {
+    @VisibleForTesting
+    boolean allWindowsDrawn() {
         for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
-            if (!mWindowingModeTransitionInfo.valueAt(index).loggedWindowsDrawn) {
+            if (mWindowingModeTransitionInfo.valueAt(index).numUndrawnActivities != 0) {
                 return false;
             }
         }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index fb4de01..3853841 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -41,6 +41,10 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.activityTypeToString;
 import static android.content.Intent.ACTION_MAIN;
 import static android.content.Intent.CATEGORY_HOME;
@@ -54,14 +58,19 @@
 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
+import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
+import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
 import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
 import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
+import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
+import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
@@ -72,6 +81,8 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
 import static android.content.res.Configuration.EMPTY;
@@ -80,14 +91,29 @@
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
+import static android.os.Build.VERSION_CODES.HONEYCOMB;
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Process.SYSTEM_UID;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.view.Display.COLOR_MODE_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
+import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 
 import static com.android.server.am.ActivityRecordProto.APP_WINDOW_TOKEN;
 import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
@@ -98,6 +124,8 @@
 import static com.android.server.am.ActivityRecordProto.VISIBLE;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
@@ -145,12 +173,51 @@
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
+import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
+import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
+import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
+import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
+import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
+import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
+import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
+import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
+import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
+import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.AppWindowTokenProto.NAME;
+import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
+import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
+import static com.android.server.wm.AppWindowTokenProto.REMOVED;
+import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
+import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
+import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
+import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
+import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
+import static com.android.server.wm.IdentifierProto.HASH_CODE;
+import static com.android.server.wm.IdentifierProto.TITLE;
+import static com.android.server.wm.IdentifierProto.USER_ID;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
 import static com.android.server.wm.TaskPersister.DEBUG;
 import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.logWithStack;
+import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
+import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -159,7 +226,9 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Size;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
@@ -189,8 +258,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
@@ -202,6 +274,8 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
+import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArraySet;
@@ -213,21 +287,36 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.AppTransitionAnimationSpec;
 import android.view.DisplayCutout;
+import android.view.DisplayInfo;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IApplicationToken;
+import android.view.InputApplicationHandle;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationDefinition;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.animation.Animation;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.ReferrerIntent;
+import com.android.internal.R;
+import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.util.XmlUtils;
+import com.android.server.AttributeCache;
+import com.android.server.LocalServices;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.EventLogTags;
 import com.android.server.am.PendingIntentRecord;
+import com.android.server.display.color.ColorDisplayService;
+import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.protolog.common.ProtoLog;
 import com.android.server.uri.UriPermissionOwner;
 import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
 import com.android.server.wm.ActivityStack.ActivityState;
+import com.android.server.wm.WindowManagerService.H;
 
 import com.google.android.collect.Sets;
 
@@ -239,16 +328,18 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Consumer;
 
 /**
  * An entry in the history stack, representing an activity.
  */
-final class ActivityRecord extends AppWindowToken {
+final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -277,8 +368,34 @@
     // How many activities have to be scheduled to stop to force a stop pass.
     private static final int MAX_STOPPING_TO_FORCE = 3;
 
-    // TODO: Move to AppWindowToken?
+    private static final int STARTING_WINDOW_TYPE_NONE = 0;
+    private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
+    private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
+
+    /**
+     * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
+     */
+    @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
+
+    final ActivityTaskManagerService mAtmService;
     final ActivityInfo info; // activity info provided by developer in AndroidManifest
+    // Non-null only for application tokens.
+    // TODO: rename to mActivityToken
+    final ActivityRecord.Token appToken;
+    // Which user is this running for?
+    final int mUserId;
+    // The package implementing intent's component
+    // TODO: rename to mPackageName
+    final String packageName;
+    // the intent component, or target of an alias.
+    final ComponentName mActivityComponent;
+    // Has a wallpaper window as a background.
+    // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
+    // mOccludesParent field.
+    final boolean hasWallpaper;
+    // Input application handle used by the input dispatcher.
+    final InputApplicationHandle mInputApplicationHandle;
+
     final int launchedFromPid; // always the pid who started the activity.
     final int launchedFromUid; // always the uid who started the activity.
     final String launchedFromPackage; // always the package who started the activity.
@@ -348,9 +465,14 @@
     boolean visible;        // does this activity's window need to be shown?
     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
                                      // might hide this activity?
-    // TODO: figureout how to consolidate with the same variable in AppWindowToken.
+    // True if the hidden state of this token was forced to false due to a transferred starting
+    // window.
+    private boolean mHiddenSetFromTransferredStartingWindow;
+    // TODO: figureout how to consolidate with the same variable in ActivityRecord.
     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
                                         // process that it is hidden.
+    private boolean mLastDeferHidingClient; // If true we will defer setting mClientHidden to true
+                                           // and reporting to the client that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
     boolean nowVisible;     // is this activity's window visible?
     boolean mDrawn;          // is this activity's window drawn?
@@ -401,6 +523,188 @@
     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
 
+    boolean mVoiceInteraction;
+
+    private int mPendingRelaunchCount;
+
+    // True if we are current in the process of removing this app token from the display
+    private boolean mRemovingFromDisplay = false;
+
+    // Flag set while reparenting to prevent actions normally triggered by an individual parent
+    // change.
+    private boolean mReparenting;
+
+    private RemoteAnimationDefinition mRemoteAnimationDefinition;
+
+    private AnimatingActivityRegistry mAnimatingActivityRegistry;
+
+    private Task mLastParent;
+
+    // Have we told the window clients to hide themselves?
+    private boolean mClientHidden;
+
+    boolean firstWindowDrawn;
+    // Last drawn state we reported to the app token.
+    private boolean reportedDrawn;
+    private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
+            new WindowState.UpdateReportedVisibilityResults();
+
+    private boolean mUseTransferredAnimation;
+
+    /**
+     * @see #currentLaunchCanTurnScreenOn()
+     */
+    private boolean mCurrentLaunchCanTurnScreenOn = true;
+
+    /**
+     * This gets used during some open/close transitions as well as during a change transition
+     * where it represents the starting-state snapshot.
+     */
+    private AppWindowThumbnail mThumbnail;
+    private final Rect mTransitStartRect = new Rect();
+
+    /**
+     * If we are running an animation, this determines the transition type. Must be one of
+     * AppTransition.TRANSIT_* constants.
+     */
+    private int mTransit;
+
+    /**
+     * If we are running an animation, this determines the flags during this animation. Must be a
+     * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
+     */
+    private int mTransitFlags;
+    /**
+     * This leash is used to "freeze" the app surface in place after the state change, but before
+     * the animation is ready to start.
+     */
+    private SurfaceControl mTransitChangeLeash = null;
+
+    /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
+    private boolean mLastSurfaceShowing = true;
+
+    private Letterbox mLetterbox;
+
+    /**
+     * The activity is opaque and fills the entire space of this task.
+     * @see WindowContainer#fillsParent()
+     */
+    private boolean mOccludesParent;
+
+    // The input dispatching timeout for this application token in nanoseconds.
+    long mInputDispatchingTimeoutNanos;
+
+    private boolean mShowWhenLocked;
+    private boolean mInheritShownWhenLocked;
+    private boolean mTurnScreenOn;
+
+    /** Have we been asked to have this token keep the screen frozen? */
+    private boolean mFreezingScreen;
+
+    // These are used for determining when all windows associated with
+    // an activity have been drawn, so they can be made visible together
+    // at the same time.
+    // initialize so that it doesn't match mTransactionSequence which is an int.
+    private long mLastTransactionSequence = Long.MIN_VALUE;
+    private int mNumInterestingWindows;
+    private int mNumDrawnWindows;
+    boolean inPendingTransaction;
+    boolean allDrawn;
+    private boolean mLastAllDrawn;
+
+    private boolean mLastContainsShowWhenLockedWindow;
+    private boolean mLastContainsDismissKeyguardWindow;
+
+    /**
+     * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
+     * to help AR know that the app is in the process of closing but hasn't yet started closing on
+     * the WM side.
+     */
+    private boolean mWillCloseOrEnterPip;
+
+    /**
+     * The scale to fit at least one side of the activity to its parent. If the activity uses
+     * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
+     */
+    private float mSizeCompatScale = 1f;
+    /**
+     * The bounds in global coordinates for activity in size compatibility mode.
+     * @see ActivityRecord#hasSizeCompatBounds()
+     */
+    private Rect mSizeCompatBounds;
+
+    // activity is not displayed?
+    // TODO: rename to mNoDisplay
+    @VisibleForTesting
+    boolean noDisplay;
+    boolean mShowForAllUsers;
+    // TODO: Make this final
+    int mTargetSdk;
+
+    // Set to true when this app creates a surface while in the middle of an animation. In that
+    // case do not clear allDrawn until the animation completes.
+    boolean deferClearAllDrawn;
+
+    // Is this window's surface needed?  This is almost like hidden, except
+    // it will sometimes be true a little earlier: when the token has
+    // been shown, but is still waiting for its app transition to execute
+    // before making its windows shown.
+    boolean hiddenRequested;
+
+    // Last visibility state we reported to the app token.
+    boolean reportedVisible;
+
+    // Set to true when the token has been removed from the window mgr.
+    boolean removed;
+
+    boolean mDisablePreviewScreenshots;
+
+    // Information about an application starting window if displayed.
+    // Note: these are de-referenced before the starting window animates away.
+    StartingData mStartingData;
+    WindowState startingWindow;
+    WindowManagerPolicy.StartingSurface startingSurface;
+    boolean startingDisplayed;
+    boolean startingMoved;
+
+    // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
+    boolean mIsExiting;
+
+    boolean mLaunchTaskBehind;
+    boolean mEnteringAnimation;
+
+    boolean mAppStopped;
+    // A hint to override the window specified rotation animation, or -1 to use the window specified
+    // value. We use this so that we can select the right animation in the cases of starting
+    // windows, where the app hasn't had time to set a value on the window.
+    int mRotationAnimationHint = -1;
+
+    ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
+    ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
+
+    /** Whether this token should be boosted at the top of all app window tokens. */
+    @VisibleForTesting boolean mNeedsZBoost;
+
+    /** Layer used to constrain the animation to a token's stack bounds. */
+    SurfaceControl mAnimationBoundsLayer;
+
+    /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
+    boolean mNeedsAnimationBoundsLayer;
+
+    private AppSaturationInfo mLastAppSaturationInfo;
+
+    private final ColorDisplayService.ColorTransformController mColorTransformController =
+            (matrix, translation) -> mWmService.mH.post(() -> {
+                synchronized (mWmService.mGlobalLock) {
+                    if (mLastAppSaturationInfo == null) {
+                        mLastAppSaturationInfo = new AppSaturationInfo();
+                    }
+
+                    mLastAppSaturationInfo.setSaturation(matrix, translation);
+                    updateColorTransform();
+                }
+            });
+
     /**
      * Current sequencing integer of the configuration, for skipping old activity configurations.
      */
@@ -412,6 +716,10 @@
     private final Configuration mTmpConfig = new Configuration();
     private final Rect mTmpBounds = new Rect();
 
+    private final Point mTmpPoint = new Point();
+    private final Rect mTmpRect = new Rect();
+    private final Rect mTmpPrevBounds = new Rect();
+
     // Token for targeting this activity for assist purposes.
     final Binder assistToken = new Binder();
 
@@ -429,6 +737,13 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
+    }
+
+    /**
+     * Copied from old AppWindowToken.
+     */
+    @Override
+    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         final long now = SystemClock.uptimeMillis();
         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
                 pw.print(" processName="); pw.println(processName);
@@ -576,6 +891,64 @@
             pw.print("requestedVrComponent=");
             pw.println(requestedVrComponent);
         }
+        super.dump(pw, prefix, dumpAll);
+        if (appToken != null) {
+            pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
+        }
+        pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
+        pw.print(" mOrientation="); pw.println(mOrientation);
+        pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
+                + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
+                + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
+        if (paused) {
+            pw.print(prefix); pw.print("paused="); pw.println(paused);
+        }
+        if (mAppStopped) {
+            pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
+        }
+        if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
+                || allDrawn || mLastAllDrawn) {
+            pw.print(prefix); pw.print("mNumInterestingWindows=");
+            pw.print(mNumInterestingWindows);
+            pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
+            pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
+            pw.print(" allDrawn="); pw.print(allDrawn);
+            pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
+            pw.println(")");
+        }
+        if (inPendingTransaction) {
+            pw.print(prefix); pw.print("inPendingTransaction=");
+            pw.println(inPendingTransaction);
+        }
+        if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
+            pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
+            pw.print(" removed="); pw.print(removed);
+            pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
+            pw.print(" mIsExiting="); pw.println(mIsExiting);
+        }
+        if (startingWindow != null || startingSurface != null
+                || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
+            pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
+            pw.print(" startingSurface="); pw.print(startingSurface);
+            pw.print(" startingDisplayed="); pw.print(startingDisplayed);
+            pw.print(" startingMoved="); pw.print(startingMoved);
+            pw.println(" mHiddenSetFromTransferredStartingWindow="
+                    + mHiddenSetFromTransferredStartingWindow);
+        }
+        if (!mFrozenBounds.isEmpty()) {
+            pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
+            pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
+        }
+        if (mPendingRelaunchCount != 0) {
+            pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
+        }
+        if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
+            pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
+                    + mSizeCompatBounds);
+        }
+        if (mRemovingFromDisplay) {
+            pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
+        }
         if (lastVisibleTime != 0 || nowVisible) {
             pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
                     pw.print(" lastVisibleTime=");
@@ -587,7 +960,8 @@
             pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
         }
         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
-            pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
+            pw.print(prefix); pw.print("deferRelaunchUntilPaused=");
+                    pw.print(deferRelaunchUntilPaused);
                     pw.print(" configChangeFlags=");
                     pw.println(Integer.toHexString(configChangeFlags));
         }
@@ -901,6 +1275,167 @@
         this.task = task;
     }
 
+    Task getTask() {
+        return (Task) getParent();
+    }
+
+    TaskStack getStack() {
+        final Task task = getTask();
+        if (task != null) {
+            return task.mStack;
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    void onParentChanged() {
+        super.onParentChanged();
+
+        final Task task = getTask();
+
+        // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
+        // access visual elements like the {@link DisplayContent}. We must remove any associations
+        // such as animations.
+        if (!mReparenting) {
+            if (task == null) {
+                // It is possible we have been marked as a closing app earlier. We must remove ourselves
+                // from this list so we do not participate in any future animations.
+                if (getDisplayContent() != null) {
+                    getDisplayContent().mClosingApps.remove(this);
+                }
+            } else if (mLastParent != null && mLastParent.mStack != null) {
+                task.mStack.mExitingActivities.remove(this);
+            }
+        }
+        final TaskStack stack = getStack();
+
+        // If we reparent, make sure to remove ourselves from the old animation registry.
+        if (mAnimatingActivityRegistry != null) {
+            mAnimatingActivityRegistry.notifyFinished(this);
+        }
+        mAnimatingActivityRegistry = stack != null
+                ? stack.getAnimatingActivityRegistry()
+                : null;
+
+        mLastParent = task;
+
+        updateColorTransform();
+    }
+
+    private void updateColorTransform() {
+        if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
+            getPendingTransaction().setColorTransform(mSurfaceControl,
+                    mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
+            mWmService.scheduleAnimationLocked();
+        }
+    }
+
+    @Override
+    void onDisplayChanged(DisplayContent dc) {
+        DisplayContent prevDc = mDisplayContent;
+        super.onDisplayChanged(dc);
+        if (prevDc == null || prevDc == mDisplayContent) {
+            return;
+        }
+
+        if (prevDc.mOpeningApps.remove(this)) {
+            // Transfer opening transition to new display.
+            mDisplayContent.mOpeningApps.add(this);
+            mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
+            mDisplayContent.executeAppTransition();
+        }
+
+        if (prevDc.mChangingApps.remove(this)) {
+            // This gets called *after* the ActivityRecord has been reparented to the new display.
+            // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
+            // so this token is now "frozen" while waiting for the animation to start on prevDc
+            // (which will be cancelled since the window is no-longer a child). However, since this
+            // is no longer a child of prevDc, this won't be notified of the cancelled animation,
+            // so we need to cancel the change transition here.
+            clearChangeLeash(getPendingTransaction(), true /* cancel */);
+        }
+        prevDc.mClosingApps.remove(this);
+
+        if (prevDc.mFocusedApp == this) {
+            prevDc.setFocusedApp(null);
+            final TaskStack stack = dc.getTopStack();
+            if (stack != null) {
+                final Task task = stack.getTopChild();
+                if (task != null && task.getTopChild() == this) {
+                    dc.setFocusedApp(this);
+                }
+            }
+        }
+
+        if (mLetterbox != null) {
+            mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
+        }
+    }
+
+    void layoutLetterbox(WindowState winHint) {
+        final WindowState w = findMainWindow();
+        if (w == null || winHint != null && w != winHint) {
+            return;
+        }
+        final boolean surfaceReady = w.isDrawnLw()  // Regular case
+                || w.mWinAnimator.mSurfaceDestroyDeferred  // The preserved surface is still ready.
+                || w.isDragResizeChanged();  // Waiting for relayoutWindow to call preserveSurface.
+        final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
+        if (needsLetterbox) {
+            if (mLetterbox == null) {
+                mLetterbox = new Letterbox(() -> makeChildSurface(null),
+                        mWmService.mTransactionFactory);
+                mLetterbox.attachInput(w);
+            }
+            getPosition(mTmpPoint);
+            // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
+            // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
+            // is also applied to the task).
+            Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
+                    ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
+            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
+        } else if (mLetterbox != null) {
+            mLetterbox.hide();
+        }
+    }
+
+    void updateLetterboxSurface(WindowState winHint) {
+        final WindowState w = findMainWindow();
+        if (w != winHint && winHint != null && w != null) {
+            return;
+        }
+        layoutLetterbox(winHint);
+        if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
+            mLetterbox.applySurfaceChanges(getPendingTransaction());
+        }
+    }
+
+    Rect getLetterboxInsets() {
+        if (mLetterbox != null) {
+            return mLetterbox.getInsets();
+        } else {
+            return new Rect();
+        }
+    }
+
+    /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
+    void getLetterboxInnerBounds(Rect outBounds) {
+        if (mLetterbox != null) {
+            outBounds.set(mLetterbox.getInnerFrame());
+        } else {
+            outBounds.setEmpty();
+        }
+    }
+
+    /**
+     * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
+     * the given {@code rect}.
+     */
+    boolean isLetterboxOverlappingWith(Rect rect) {
+        return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
+    }
+
     static class Token extends IApplicationToken.Stub {
         private WeakReference<ActivityRecord> weakActivity;
         private final String name;
@@ -984,16 +1519,82 @@
             ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
             boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
             ActivityOptions options, ActivityRecord sourceRecord) {
-        super(_service.mWindowManager, _service, new Token(_intent), aInfo, options, _intent,
-                null /* displayContent */);
+        super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
+                null /* displayContent */, false /* ownerCanManageAppTokens */);
+
+        mAtmService = _service;
+        appToken = (Token) token;
+        info = aInfo;
+        mUserId = UserHandle.getUserId(info.applicationInfo.uid);
+        packageName = info.applicationInfo.packageName;
+        mInputApplicationHandle = new InputApplicationHandle(appToken);
+        intent = _intent;
+
+        // If the class name in the intent doesn't match that of the target, this is probably an
+        // alias. We have to create a new ComponentName object to keep track of the real activity
+        // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
+        if (info.targetActivity == null
+                || (info.targetActivity.equals(intent.getComponent().getClassName())
+                && (info.launchMode == LAUNCH_MULTIPLE
+                || info.launchMode == LAUNCH_SINGLE_TOP))) {
+            mActivityComponent = intent.getComponent();
+        } else {
+            mActivityComponent =
+                    new ComponentName(info.packageName, info.targetActivity);
+        }
+
+        mTargetSdk = info.applicationInfo.targetSdkVersion;
+        mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
+        setOrientation(info.screenOrientation);
+        mRotationAnimationHint = info.rotationAnimation;
+
+        mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
+        mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
+        mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
+
+        int realTheme = info.getThemeResource();
+        if (realTheme == Resources.ID_NULL) {
+            realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
+                    ? android.R.style.Theme : android.R.style.Theme_Holo;
+        }
+
+        final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+                realTheme, com.android.internal.R.styleable.Window, mUserId);
+
+        if (ent != null) {
+            mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
+            hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
+            noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
+        } else {
+            hasWallpaper = false;
+            noDisplay = false;
+        }
+
+        if (options != null) {
+            mLaunchTaskBehind = options.getLaunchTaskBehind();
+
+            final int rotationAnimation = options.getRotationAnimationHint();
+            // Only override manifest supplied option if set.
+            if (rotationAnimation >= 0) {
+                mRotationAnimationHint = rotationAnimation;
+            }
+        }
+
+        // Application tokens start out hidden.
+        setHidden(true);
+        hiddenRequested = true;
+
+        ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
+                ColorDisplayService.ColorDisplayServiceInternal.class);
+        cds.attachColorTransformController(packageName, mUserId,
+                new WeakReference<>(mColorTransformController));
+
         appToken.attach(this);
 
         mRootActivityContainer = _service.mRootActivityContainer;
-        info = aInfo;
         launchedFromPid = _launchedFromPid;
         launchedFromUid = _launchedFromUid;
         launchedFromPackage = _launchedFromPackage;
-        intent = _intent;
         shortComponentName = _intent.getComponent().flattenToShortString();
         resolvedType = _resolvedType;
         componentSpecified = _componentSpecified;
@@ -1075,6 +1676,12 @@
         }
     }
 
+    @Override
+    ActivityRecord asActivityRecord() {
+        // I am an activity record!
+        return this;
+    }
+
     void setProcess(WindowProcessController proc) {
         app = proc;
         final ActivityRecord root = task != null ? task.getRootActivity() : null;
@@ -1091,22 +1698,274 @@
         return hasProcess() && app.hasThread();
     }
 
+    void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
+            long inputDispatchingTimeoutNanos) {
+        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
+        mVoiceInteraction = voiceInteraction;
+        onDisplayChanged(dc);
+
+        // Application tokens start out hidden.
+        setHidden(true);
+        hiddenRequested = true;
+    }
+
     boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
             boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "setAppStartingWindow: token=%s"
-                    + " pkg=%s transferFrom=%s newTask=%b taskSwitch=%b processRunning=%b"
-                    + " allowTaskSnapshot=%b", appToken, pkg, transferFrom, newTask, taskSwitch,
-                processRunning, allowTaskSnapshot);
-        if (getParent() == null) {
-            Slog.w(TAG_WM, "Attempted to start a window to an app token not having attached to any"
-                    + " task: " + appToken);
+        // If the display is frozen, we won't do anything until the actual window is
+        // displayed so there is no reason to put in the starting window.
+        if (!okToDisplay()) {
             return false;
         }
-        return super.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
-                labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
-                processRunning, allowTaskSnapshot, activityCreated, fromRecents);
+
+        if (mStartingData != null) {
+            return false;
+        }
+
+        final WindowState mainWin = findMainWindow();
+        if (mainWin != null && mainWin.mWinAnimator.getShown()) {
+            // App already has a visible window...why would you want a starting window?
+            return false;
+        }
+
+        final ActivityManager.TaskSnapshot snapshot =
+                mWmService.mTaskSnapshotController.getSnapshot(
+                        getTask().mTaskId, getTask().mUserId,
+                        false /* restoreFromDisk */, false /* reducedResolution */);
+        final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
+                allowTaskSnapshot, activityCreated, fromRecents, snapshot);
+
+        if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
+            return createSnapshot(snapshot);
+        }
+
+        // If this is a translucent window, then don't show a starting window -- the current
+        // effect (a full-screen opaque starting window that fades away to the real contents
+        // when it is ready) does not work for this.
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
+        if (theme != 0) {
+            AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
+                    com.android.internal.R.styleable.Window,
+                    mWmService.mCurrentUserId);
+            if (ent == null) {
+                // Whoops!  App doesn't exist. Um. Okay. We'll just pretend like we didn't
+                // see that.
+                return false;
+            }
+            final boolean windowIsTranslucent = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+            final boolean windowIsFloating = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowIsFloating, false);
+            final boolean windowShowWallpaper = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowShowWallpaper, false);
+            final boolean windowDisableStarting = ent.array.getBoolean(
+                    com.android.internal.R.styleable.Window_windowDisablePreview, false);
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
+                    windowIsTranslucent, windowIsFloating, windowShowWallpaper);
+            if (windowIsTranslucent) {
+                return false;
+            }
+            if (windowIsFloating || windowDisableStarting) {
+                return false;
+            }
+            if (windowShowWallpaper) {
+                if (getDisplayContent().mWallpaperController
+                        .getWallpaperTarget() == null) {
+                    // If this theme is requesting a wallpaper, and the wallpaper
+                    // is not currently visible, then this effectively serves as
+                    // an opaque window and our starting window transition animation
+                    // can still work.  We just need to make sure the starting window
+                    // is also showing the wallpaper.
+                    windowFlags |= FLAG_SHOW_WALLPAPER;
+                } else {
+                    return false;
+                }
+            }
+        }
+
+        if (transferStartingWindow(transferFrom)) {
+            return true;
+        }
+
+        // There is no existing starting window, and we don't want to create a splash screen, so
+        // that's it!
+        if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+            return false;
+        }
+
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
+        mStartingData = new SplashScreenStartingData(mWmService, pkg,
+                theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
+                getMergedOverrideConfiguration());
+        scheduleAddStartingWindow();
+        return true;
+    }
+
+    private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
+        if (snapshot == null) {
+            return false;
+        }
+
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
+        mStartingData = new SnapshotStartingData(mWmService, snapshot);
+        scheduleAddStartingWindow();
+        return true;
+    }
+
+    void scheduleAddStartingWindow() {
+        // Note: we really want to do sendMessageAtFrontOfQueue() because we
+        // want to process the message ASAP, before any other queued
+        // messages.
+        if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
+            mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
+        }
+    }
+
+    private class AddStartingWindow implements Runnable {
+
+        @Override
+        public void run() {
+            // Can be accessed without holding the global lock
+            final StartingData startingData;
+            synchronized (mWmService.mGlobalLock) {
+                // There can only be one adding request, silly caller!
+                mWmService.mAnimationHandler.removeCallbacks(this);
+
+                if (mStartingData == null) {
+                    // Animation has been canceled... do nothing.
+                    ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                            "startingData was nulled out before handling"
+                                    + " mAddStartingWindow: %s", ActivityRecord.this);
+                    return;
+                }
+                startingData = mStartingData;
+            }
+
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
+                    this, startingData);
+
+
+            WindowManagerPolicy.StartingSurface surface = null;
+            try {
+                surface = startingData.createStartingSurface(ActivityRecord.this);
+            } catch (Exception e) {
+                Slog.w(TAG, "Exception when adding starting window", e);
+            }
+            if (surface != null) {
+                boolean abort = false;
+                synchronized (mWmService.mGlobalLock) {
+                    // If the window was successfully added, then
+                    // we need to remove it.
+                    if (removed || mStartingData == null) {
+                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                                "Aborted starting %s: removed=%b startingData=%s",
+                                ActivityRecord.this, removed, mStartingData);
+
+                        startingWindow = null;
+                        mStartingData = null;
+                        abort = true;
+                    } else {
+                        startingSurface = surface;
+                    }
+                    if (!abort) {
+                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                                "Added starting %s: startingWindow=%s startingView=%s",
+                                ActivityRecord.this, startingWindow, startingSurface);
+                    }
+                }
+                if (abort) {
+                    surface.remove();
+                }
+            } else {
+                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
+                        ActivityRecord.this);
+            }
+        }
+    }
+
+    private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
+
+    private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
+            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
+            ActivityManager.TaskSnapshot snapshot) {
+        if (getDisplayContent().mAppTransition.getAppTransition()
+                == TRANSIT_DOCK_TASK_FROM_RECENTS) {
+            // TODO(b/34099271): Remove this statement to add back the starting window and figure
+            // out why it causes flickering, the starting window appears over the thumbnail while
+            // the docked from recents transition occurs
+            return STARTING_WINDOW_TYPE_NONE;
+        } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
+            return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+        } else if (taskSwitch && allowTaskSnapshot) {
+            if (mWmService.mLowRamTaskSnapshotsAndRecents) {
+                // For low RAM devices, we use the splash screen starting window instead of the
+                // task snapshot starting window.
+                return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+            }
+            return snapshot == null ? STARTING_WINDOW_TYPE_NONE
+                    : snapshotOrientationSameAsTask(snapshot) || fromRecents
+                            ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+        } else {
+            return STARTING_WINDOW_TYPE_NONE;
+        }
+    }
+
+    private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
+        if (snapshot == null) {
+            return false;
+        }
+        return getTask().getConfiguration().orientation == snapshot.getOrientation();
+    }
+
+    void removeStartingWindow() {
+        if (startingWindow == null) {
+            if (mStartingData != null) {
+                // Starting window has not been added yet, but it is scheduled to be added.
+                // Go ahead and cancel the request.
+                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
+                mStartingData = null;
+            }
+            return;
+        }
+
+        final WindowManagerPolicy.StartingSurface surface;
+        if (mStartingData != null) {
+            surface = startingSurface;
+            mStartingData = null;
+            startingSurface = null;
+            startingWindow = null;
+            startingDisplayed = false;
+            if (surface == null) {
+                ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                        "startingWindow was set but startingSurface==null, couldn't "
+                                + "remove");
+
+                return;
+            }
+        } else {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                    "Tried to remove starting window but startingWindow was null: %s",
+                    this);
+            return;
+        }
+
+        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
+                        + " startingView=%s Callers=%s",
+                this, startingWindow, startingSurface, Debug.getCallers(5));
+
+
+        // Use the same thread to remove the window as we used to add it, as otherwise we end up
+        // with things in the view hierarchy being called from different threads.
+        mWmService.mAnimationHandler.post(() -> {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
+            try {
+                surface.remove();
+            } catch (Exception e) {
+                Slog.w(TAG_WM, "Exception when removing starting window", e);
+            }
+        });
     }
 
     void removeWindowContainer() {
@@ -1147,7 +2006,44 @@
                     + " r=" + this + " (" + prevTask.getStackId() + ")");
         }
 
-        reparent(newTask.getTask(), position);
+        final Task task = newTask.getTask();
+        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving app token=%s"
+                + " to task=%d at %d", this, task.mTaskId, position);
+
+        if (task == null) {
+            throw new IllegalArgumentException("reparent: could not find task");
+        }
+        final Task currentTask = getTask();
+        if (task == currentTask) {
+            throw new IllegalArgumentException(
+                    "window token=" + this + " already child of task=" + currentTask);
+        }
+
+        if (currentTask.mStack != task.mStack) {
+            throw new IllegalArgumentException(
+                    "window token=" + this + " current task=" + currentTask
+                            + " belongs to a different stack than " + task);
+        }
+
+        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reParentWindowToken: removing window token=%s"
+                + " from task=%s"  , this, currentTask);
+        final DisplayContent prevDisplayContent = getDisplayContent();
+
+        mReparenting = true;
+
+        getParent().removeChild(this);
+        task.addChild(this, position);
+
+        mReparenting = false;
+
+        // Relayout display(s).
+        final DisplayContent displayContent = task.getDisplayContent();
+        displayContent.setLayoutNeeded();
+        if (prevDisplayContent != displayContent) {
+            onDisplayChanged(displayContent);
+            prevDisplayContent.setLayoutNeeded();
+        }
+        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
 
         // Reparenting prevents informing the parent stack of activity removal in the case that
         // the new stack has the same parent. we must manually signal here if this is not the case.
@@ -1252,8 +2148,22 @@
         return stack != null ? stack.getDisplay() : null;
     }
 
+    @Override
+    boolean fillsParent() {
+        return occludesParent();
+    }
+
+    /** Returns true if this activity is opaque and fills the entire space of this task. */
+    boolean occludesParent() {
+        return mOccludesParent;
+    }
+
     boolean setOccludesParent(boolean occludesParent) {
-        final boolean changed = super.setOccludesParent(occludesParent);
+        final boolean changed = occludesParent != mOccludesParent;
+        mOccludesParent = occludesParent;
+        setMainWindowOpaque(occludesParent);
+        mWmService.mWindowPlacerLocked.requestTraversal();
+
         if (changed && task != null) {
             if (!occludesParent) {
                 getActivityStack().convertActivityToTranslucent(this);
@@ -1270,6 +2180,15 @@
         return changed;
     }
 
+    void setMainWindowOpaque(boolean isOpaque) {
+        final WindowState win = findMainWindow();
+        if (win == null) {
+            return;
+        }
+        isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
+        win.mWinAnimator.setOpaqueLocked(isOpaque);
+    }
+
     void takeFromHistory() {
         if (inHistory) {
             inHistory = false;
@@ -1421,6 +2340,22 @@
     }
 
     /**
+     * Sets if this AWT is in the process of closing or entering PIP.
+     * {@link #mWillCloseOrEnterPip}}
+     */
+    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
+        mWillCloseOrEnterPip = willCloseOrEnterPip;
+    }
+
+    /**
+     * Returns whether this AWT is considered closing. Conditions are either
+     * 1. Is this app animating and was requested to be hidden
+     * 2. App is delayed closing since it might enter PIP.
+     */
+    boolean isClosingOrEnteringPip() {
+        return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
+    }
+    /**
      * @return Whether AppOps allows this package to enter picture-in-picture.
      */
     private boolean checkEnterPictureInPictureAppOpsState() {
@@ -1428,6 +2363,27 @@
                 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
     }
 
+    boolean isAlwaysFocusable() {
+        return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
+    }
+
+    // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
+    // focusable means resumeable. I guess with that in mind maybe we should rename the other
+    // method to isResumeable() or something like that.
+    boolean windowsAreFocusable() {
+        if (mTargetSdk < Build.VERSION_CODES.Q) {
+            final int pid = getPid();
+            final ActivityRecord topFocusedAppOfMyProcess =
+                    mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
+            if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
+                // For the apps below Q, there can be only one app which has the focused window per
+                // process, because legacy apps may not be ready for a multi-focus system.
+                return false;
+            }
+        }
+        return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
+    }
+
     /** Move activity with its stack to front and make the stack focused. */
     boolean moveFocusableActivityToTop(String reason) {
         if (!isFocusable()) {
@@ -2076,6 +3032,106 @@
         clearRelaunching();
     }
 
+    boolean isRelaunching() {
+        return mPendingRelaunchCount > 0;
+    }
+
+    boolean shouldFreezeBounds() {
+        final Task task = getTask();
+
+        // For freeform windows, we can't freeze the bounds at the moment because this would make
+        // the resizing unresponsive.
+        if (task == null || task.inFreeformWindowingMode()) {
+            return false;
+        }
+
+        // We freeze the bounds while drag resizing to deal with the time between
+        // the divider/drag handle being released, and the handling it's new
+        // configuration. If we are relaunched outside of the drag resizing state,
+        // we need to be careful not to do this.
+        return getTask().isDragResizing();
+    }
+
+    void startRelaunching() {
+        if (shouldFreezeBounds()) {
+            freezeBounds();
+        }
+
+        // In the process of tearing down before relaunching, the app will
+        // try and clean up it's child surfaces. We need to prevent this from
+        // happening, so we sever the children, transfering their ownership
+        // from the client it-self to the parent surface (owned by us).
+        detachChildren();
+
+        mPendingRelaunchCount++;
+    }
+
+    /**
+     * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
+     * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
+     * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
+     * with a queue.
+     */
+    private void freezeBounds() {
+        final Task task = getTask();
+        mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
+
+        if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
+            // We didn't call prepareFreezingBounds on the task, so use the current value.
+            mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
+        } else {
+            mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
+        }
+        // Calling unset() to make it equal to Configuration.EMPTY.
+        task.mPreparedFrozenMergedConfig.unset();
+    }
+
+    void detachChildren() {
+        SurfaceControl.openTransaction();
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.mWinAnimator.detachChildren();
+        }
+        SurfaceControl.closeTransaction();
+    }
+
+    void finishRelaunching() {
+        unfreezeBounds();
+
+        if (mPendingRelaunchCount > 0) {
+            mPendingRelaunchCount--;
+        } else {
+            // Update keyguard flags upon finishing relaunch.
+            checkKeyguardFlagsChanged();
+        }
+    }
+
+    void clearRelaunching() {
+        if (mPendingRelaunchCount == 0) {
+            return;
+        }
+        unfreezeBounds();
+        mPendingRelaunchCount = 0;
+    }
+
+    /**
+     * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
+     */
+    private void unfreezeBounds() {
+        if (mFrozenBounds.isEmpty()) {
+            return;
+        }
+        mFrozenBounds.remove();
+        if (!mFrozenMergedConfig.isEmpty()) {
+            mFrozenMergedConfig.remove();
+        }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            win.onUnfreezeBounds();
+        }
+        mWmService.mWindowPlacerLocked.performSurfacePlacement();
+    }
+
     /**
      * Perform clean-up of service connections in an activity record.
      */
@@ -2087,6 +3143,504 @@
         mServiceConnectionsHolder.disconnectActivityFromServices();
     }
 
+    @Override
+    void removeImmediately() {
+        onRemovedFromDisplay();
+        super.removeImmediately();
+    }
+
+    @Override
+    void removeIfPossible() {
+        mIsExiting = false;
+        removeAllWindowsIfPossible();
+        removeImmediately();
+    }
+
+    @Override
+    boolean checkCompleteDeferredRemoval() {
+        if (mIsExiting) {
+            removeIfPossible();
+        }
+        return super.checkCompleteDeferredRemoval();
+    }
+
+    void onRemovedFromDisplay() {
+        if (mRemovingFromDisplay) {
+            return;
+        }
+        mRemovingFromDisplay = true;
+
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
+
+        boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
+
+        getDisplayContent().mOpeningApps.remove(this);
+        getDisplayContent().mChangingApps.remove(this);
+        getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
+        mWmService.mTaskSnapshotController.onAppRemoved(this);
+        waitingToShow = false;
+        if (getDisplayContent().mClosingApps.contains(this)) {
+            delayed = true;
+        } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
+            getDisplayContent().mClosingApps.add(this);
+            delayed = true;
+        }
+
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
+                getAnimation(), isSelfAnimating());
+
+        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
+                + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
+
+        if (mStartingData != null) {
+            removeStartingWindow();
+        }
+
+        // If this window was animating, then we need to ensure that the app transition notifies
+        // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
+        // so add to that list now
+        if (isSelfAnimating()) {
+            getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
+        }
+
+        final TaskStack stack = getStack();
+        if (delayed && !isEmpty()) {
+            // set the token aside because it has an active animation to be finished
+            ProtoLog.v(WM_DEBUG_ADD_REMOVE,
+                    "removeAppToken make exiting: %s", this);
+            if (stack != null) {
+                stack.mExitingActivities.add(this);
+            }
+            mIsExiting = true;
+        } else {
+            // Make sure there is no animation running on this token, so any windows associated
+            // with it will be removed as soon as their animations are complete
+            cancelAnimation();
+            if (stack != null) {
+                stack.mExitingActivities.remove(this);
+            }
+            removeIfPossible();
+        }
+
+        removed = true;
+        stopFreezingScreen(true, true);
+
+        final DisplayContent dc = getDisplayContent();
+        if (dc.mFocusedApp == this) {
+            ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
+                    "Removing focused app token:%s displayId=%d", this,
+                    dc.getDisplayId());
+            dc.setFocusedApp(null);
+            mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
+        }
+        if (mLetterbox != null) {
+            mLetterbox.destroy();
+            mLetterbox = null;
+        }
+
+        if (!delayed) {
+            updateReportedVisibilityLocked();
+        }
+
+        // Reset the last saved PiP snap fraction on removal.
+        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
+
+        mRemovingFromDisplay = false;
+    }
+
+    /**
+     * Returns true if the new child window we are adding to this token is considered greater than
+     * the existing child window in this token in terms of z-order.
+     */
+    @Override
+    protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
+            WindowState existingWindow) {
+        final int type1 = newWindow.mAttrs.type;
+        final int type2 = existingWindow.mAttrs.type;
+
+        // Base application windows should be z-ordered BELOW all other windows in the app token.
+        if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
+            return false;
+        } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
+            return true;
+        }
+
+        // Starting windows should be z-ordered ABOVE all other windows in the app token.
+        if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
+            return true;
+        } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
+            return false;
+        }
+
+        // Otherwise the new window is greater than the existing window.
+        return true;
+    }
+
+    /**
+     * @return {@code true} if starting window is in app's hierarchy.
+     */
+    boolean hasStartingWindow() {
+        if (startingDisplayed || mStartingData != null) {
+            return true;
+        }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean isLastWindow(WindowState win) {
+        return mChildren.size() == 1 && mChildren.get(0) == win;
+    }
+
+    @Override
+    void addWindow(WindowState w) {
+        super.addWindow(w);
+
+        boolean gotReplacementWindow = false;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState candidate = mChildren.get(i);
+            gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
+        }
+
+        // if we got a replacement window, reset the timeout to give drawing more time
+        if (gotReplacementWindow) {
+            mWmService.scheduleWindowReplacementTimeouts(this);
+        }
+        checkKeyguardFlagsChanged();
+    }
+
+    @Override
+    void removeChild(WindowState child) {
+        if (!mChildren.contains(child)) {
+            // This can be true when testing.
+            return;
+        }
+        super.removeChild(child);
+        checkKeyguardFlagsChanged();
+        updateLetterboxSurface(child);
+    }
+
+    private boolean waitingForReplacement() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState candidate = mChildren.get(i);
+            if (candidate.waitingForReplacement()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void onWindowReplacementTimeout() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            (mChildren.get(i)).onWindowReplacementTimeout();
+        }
+    }
+
+    void setAppLayoutChanges(int changes, String reason) {
+        if (!mChildren.isEmpty()) {
+            final DisplayContent dc = getDisplayContent();
+            dc.pendingLayoutChanges |= changes;
+            if (DEBUG_LAYOUT_REPEATS) {
+                mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
+            }
+        }
+    }
+
+    void removeReplacedWindowIfNeeded(WindowState replacement) {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            if (win.removeReplacedWindowIfNeeded(replacement)) {
+                return;
+            }
+        }
+    }
+
+    boolean transferStartingWindow(IBinder transferFrom) {
+        final ActivityRecord fromActivity = getDisplayContent().getActivityRecord(transferFrom);
+        if (fromActivity == null) {
+            return false;
+        }
+
+        final WindowState tStartingWindow = fromActivity.startingWindow;
+        if (tStartingWindow != null && fromActivity.startingSurface != null) {
+            // In this case, the starting icon has already been displayed, so start
+            // letting windows get shown immediately without any more transitions.
+            getDisplayContent().mSkipAppTransitionAnimation = true;
+
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
+                    + " from %s to %s", tStartingWindow, fromActivity, this);
+
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                // Transfer the starting window over to the new token.
+                mStartingData = fromActivity.mStartingData;
+                startingSurface = fromActivity.startingSurface;
+                startingDisplayed = fromActivity.startingDisplayed;
+                fromActivity.startingDisplayed = false;
+                startingWindow = tStartingWindow;
+                reportedVisible = fromActivity.reportedVisible;
+                fromActivity.mStartingData = null;
+                fromActivity.startingSurface = null;
+                fromActivity.startingWindow = null;
+                fromActivity.startingMoved = true;
+                tStartingWindow.mToken = this;
+                tStartingWindow.mActivityRecord = this;
+
+                ProtoLog.v(WM_DEBUG_ADD_REMOVE,
+                        "Removing starting %s from %s", tStartingWindow, fromActivity);
+                fromActivity.removeChild(tStartingWindow);
+                fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
+                fromActivity.mHiddenSetFromTransferredStartingWindow = false;
+                addWindow(tStartingWindow);
+
+                // Propagate other interesting state between the tokens. If the old token is displayed,
+                // we should immediately force the new one to be displayed. If it is animating, we need
+                // to move that animation to the new one.
+                if (fromActivity.allDrawn) {
+                    allDrawn = true;
+                    deferClearAllDrawn = fromActivity.deferClearAllDrawn;
+                }
+                if (fromActivity.firstWindowDrawn) {
+                    firstWindowDrawn = true;
+                }
+                if (!fromActivity.isHidden()) {
+                    setHidden(false);
+                    hiddenRequested = false;
+                    mHiddenSetFromTransferredStartingWindow = true;
+                }
+                setClientHidden(fromActivity.mClientHidden);
+
+                transferAnimation(fromActivity);
+
+                // When transferring an animation, we no longer need to apply an animation to the
+                // the token we transfer the animation over. Thus, set this flag to indicate we've
+                // transferred the animation.
+                mUseTransferredAnimation = true;
+
+                mWmService.updateFocusedWindowLocked(
+                        UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
+                getDisplayContent().setLayoutNeeded();
+                mWmService.mWindowPlacerLocked.performSurfacePlacement();
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+            return true;
+        } else if (fromActivity.mStartingData != null) {
+            // The previous app was getting ready to show a
+            // starting window, but hasn't yet done so.  Steal it!
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
+                    "Moving pending starting from %s to %s", fromActivity, this);
+            mStartingData = fromActivity.mStartingData;
+            fromActivity.mStartingData = null;
+            fromActivity.startingMoved = true;
+            scheduleAddStartingWindow();
+            return true;
+        }
+
+        // TODO: Transfer thumbnail
+
+        return false;
+    }
+
+    /**
+     * Tries to transfer the starting window from a token that's above ourselves in the task but
+     * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
+     * activity M in the same task. Now, when reopening the task, T starts on top of M but then
+     * immediately finishes after, so we have to transfer T to M.
+     */
+    void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
+        final Task task = getTask();
+        for (int i = task.mChildren.size() - 1; i >= 0; i--) {
+            final ActivityRecord fromActivity = task.mChildren.get(i);
+            if (fromActivity == this) {
+                return;
+            }
+            if (fromActivity.hiddenRequested && transferStartingWindow(fromActivity.token)) {
+                return;
+            }
+        }
+    }
+
+    void checkKeyguardFlagsChanged() {
+        final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
+        final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
+        if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
+                || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
+            mWmService.notifyKeyguardFlagsChanged(null /* callback */,
+                    getDisplayContent().getDisplayId());
+        }
+        mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
+        mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
+    }
+
+    boolean containsDismissKeyguardWindow() {
+        // Window state is transient during relaunch. We are not guaranteed to be frozen during the
+        // entirety of the relaunch.
+        if (isRelaunching()) {
+            return mLastContainsDismissKeyguardWindow;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean containsShowWhenLockedWindow() {
+        // When we are relaunching, it is possible for us to be unfrozen before our previous
+        // windows have been added back. Using the cached value ensures that our previous
+        // showWhenLocked preference is honored until relaunching is complete.
+        if (isRelaunching()) {
+            return mLastContainsShowWhenLockedWindow;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    void setShowWhenLocked(boolean showWhenLocked) {
+        mShowWhenLocked = showWhenLocked;
+        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+                0 /* configChanges */, false /* preserveWindows */);
+    }
+
+    void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
+        mInheritShownWhenLocked = inheritShowWhenLocked;
+        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
+                0 /* configChanges */, false /* preserveWindows */);
+    }
+
+    /**
+     * @return {@code true} if the activity windowing mode is not
+     *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
+     *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
+     *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
+     *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
+     *         conditions a) above.
+     *         Multi-windowing mode will be exited if {@code true} is returned.
+     */
+    boolean canShowWhenLocked() {
+        if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
+            return true;
+        } else if (mInheritShownWhenLocked) {
+            final ActivityRecord r = getActivityBelow();
+            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
+                    || r.containsShowWhenLockedWindow());
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @return Whether we are allowed to show non-starting windows at the moment. We disallow
+     *         showing windows during transitions in case we have windows that have wide-color-gamut
+     *         color mode set to avoid jank in the middle of the transition.
+     */
+    boolean canShowWindows() {
+        return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
+    }
+
+    /**
+     * @return true if we have a window that has a non-default color mode set; false otherwise.
+     */
+    private boolean hasNonDefaultColorWindow() {
+        return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
+                true /* topToBottom */);
+    }
+
+    /**
+     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
+     * such activity exists.
+     */
+    @Nullable
+    private ActivityRecord getActivityBelow() {
+        final Task task = getTask();
+        final int pos = task.mChildren.indexOf(this);
+        if (pos == -1) {
+            throw new IllegalStateException("Activity not found in its task");
+        }
+        return pos == 0 ? null : task.getChildAt(pos - 1);
+    }
+
+    WindowState getImeTargetBelowWindow(WindowState w) {
+        final int index = mChildren.indexOf(w);
+        if (index > 0) {
+            final WindowState target = mChildren.get(index - 1);
+            if (target.canBeImeTarget()) {
+                return target;
+            }
+        }
+        return null;
+    }
+
+    WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
+        WindowState candidate = null;
+        for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            if (w.mRemoved) {
+                continue;
+            }
+            if (candidate == null) {
+                candidate = w;
+            }
+        }
+        return candidate;
+    }
+
+    @Override
+    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
+        // For legacy reasons we process the TaskStack.mExitingActivities first in DisplayContent
+        // before the non-exiting app tokens. So, we skip the exiting app tokens here.
+        // TODO: Investigate if we need to continue to do this or if we can just process them
+        // in-order.
+        if (mIsExiting && !waitingForReplacement()) {
+            return false;
+        }
+        return forAllWindowsUnchecked(callback, traverseTopToBottom);
+    }
+
+    @Override
+    void forAllActivities(Consumer<ActivityRecord> callback) {
+        callback.accept(this);
+    }
+
+    boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
+            boolean traverseTopToBottom) {
+        return super.forAllWindows(callback, traverseTopToBottom);
+    }
+
+    @Override
+    protected void setLayer(Transaction t, int layer) {
+        if (!mSurfaceAnimator.hasLeash()) {
+            t.setLayer(mSurfaceControl, layer);
+        }
+    }
+
+    @Override
+    protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
+        if (!mSurfaceAnimator.hasLeash()) {
+            t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
+        }
+    }
+
+    @Override
+    protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
+        if (!mSurfaceAnimator.hasLeash()) {
+            t.reparent(mSurfaceControl, newParent);
+        }
+    }
+
     void logStartActivity(int tag, TaskRecord task) {
         final Uri data = intent.getData();
         final String strData = data != null ? data.toSafeString() : null;
@@ -2331,6 +3885,65 @@
         }
     }
 
+    void clearAllDrawn() {
+        allDrawn = false;
+        deferClearAllDrawn = false;
+    }
+
+    /**
+     * Returns whether the drawn window states of this {@link ActivityRecord} has considered every
+     * child {@link WindowState}. A child is considered if it has been passed into
+     * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
+     * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
+     * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
+     *
+     * @return {@code true} If all children have been considered, {@code false}.
+     */
+    private boolean allDrawnStatesConsidered() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState child = mChildren.get(i);
+            if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     *  Determines if the token has finished drawing. This should only be called from
+     *  {@link DisplayContent#applySurfaceChangesTransaction}
+     */
+    void updateAllDrawn() {
+        if (!allDrawn) {
+            // Number of drawn windows can be less when a window is being relaunched, wait for
+            // all windows to be launched and drawn for this token be considered all drawn.
+            final int numInteresting = mNumInterestingWindows;
+
+            // We must make sure that all present children have been considered (determined by
+            // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
+            // drawn.
+            if (numInteresting > 0 && allDrawnStatesConsidered()
+                    && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
+                if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
+                        + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
+                allDrawn = true;
+                // Force an additional layout pass where
+                // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
+                if (mDisplayContent != null) {
+                    mDisplayContent.setLayoutNeeded();
+                }
+                mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
+
+                // Notify the pinned stack upon all windows drawn. If there was an animation in
+                // progress then this signal will resume that animation.
+                final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+                if (pinnedStack != null) {
+                    pinnedStack.onAllWindowsDrawn();
+                }
+            }
+        }
+    }
+
     ActivityOptions getOptionsForTargetActivityLocked() {
         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
     }
@@ -2405,6 +4018,13 @@
         }
     }
 
+    @Override
+    boolean isVisible() {
+        // If the activity isn't hidden then it is considered visible and there is no need to check
+        // its children windows to see if they are visible.
+        return !isHidden();
+    }
+
     void setVisibility(boolean visible) {
         if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
@@ -2425,6 +4045,336 @@
         mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
     }
 
+    void setVisibility(boolean visible, boolean deferHidingClient) {
+        final AppTransition appTransition = getDisplayContent().mAppTransition;
+
+        // Don't set visibility to false if we were already not visible. This prevents WM from
+        // adding the app to the closing app list which doesn't make sense for something that is
+        // already not visible. However, set visibility to true even if we are already visible.
+        // This makes sure the app is added to the opening apps list so that the right
+        // transition can be selected.
+        // TODO: Probably a good idea to separate the concept of opening/closing apps from the
+        // concept of setting visibility...
+        if (!visible && hiddenRequested) {
+
+            if (!deferHidingClient && mLastDeferHidingClient) {
+                // We previously deferred telling the client to hide itself when visibility was
+                // initially set to false. Now we would like it to hide, so go ahead and set it.
+                mLastDeferHidingClient = deferHidingClient;
+                setClientHidden(true);
+            }
+            return;
+        }
+
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
+                appToken, visible, appTransition, isHidden(), hiddenRequested,
+                Debug.getCallers(6));
+
+        final DisplayContent displayContent = getDisplayContent();
+        displayContent.mOpeningApps.remove(this);
+        displayContent.mClosingApps.remove(this);
+        if (isInChangeTransition()) {
+            clearChangeLeash(getPendingTransaction(), true /* cancel */);
+        }
+        displayContent.mChangingApps.remove(this);
+        waitingToShow = false;
+        hiddenRequested = !visible;
+        mLastDeferHidingClient = deferHidingClient;
+
+        if (!visible) {
+            // If the app is dead while it was visible, we kept its dead window on screen.
+            // Now that the app is going invisible, we can remove it. It will be restarted
+            // if made visible again.
+            removeDeadWindows();
+        } else {
+            if (!appTransition.isTransitionSet()
+                    && appTransition.isReady()) {
+                // Add the app mOpeningApps if transition is unset but ready. This means
+                // we're doing a screen freeze, and the unfreeze will wait for all opening
+                // apps to be ready.
+                displayContent.mOpeningApps.add(this);
+            }
+            startingMoved = false;
+            // If the token is currently hidden (should be the common case), or has been
+            // stopped, then we need to set up to wait for its windows to be ready.
+            if (isHidden() || mAppStopped) {
+                clearAllDrawn();
+
+                // If the app was already visible, don't reset the waitingToShow state.
+                if (isHidden()) {
+                    waitingToShow = true;
+
+                    // If the client isn't hidden, we don't need to reset the drawing state.
+                    if (isClientHidden()) {
+                        // Let's reset the draw state in order to prevent the starting window to be
+                        // immediately dismissed when the app still has the surface.
+                        forAllWindows(w -> {
+                            if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
+                                w.mWinAnimator.resetDrawState();
+
+                                // Force add to mResizingWindows, so that we are guaranteed to get
+                                // another reportDrawn callback.
+                                w.resetLastContentInsets();
+                            }
+                        }, true /* traverseTopToBottom */);
+                    }
+                }
+            }
+
+            // In the case where we are making an app visible but holding off for a transition,
+            // we still need to tell the client to make its windows visible so they get drawn.
+            // Otherwise, we will wait on performing the transition until all windows have been
+            // drawn, they never will be, and we are sad.
+            setClientHidden(false);
+
+            requestUpdateWallpaperIfNeeded();
+
+            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
+            mAppStopped = false;
+
+            transferStartingWindowFromHiddenAboveTokenIfNeeded();
+        }
+
+        // If we are preparing an app transition, then delay changing
+        // the visibility of this token until we execute that transition.
+        if (okToAnimate() && appTransition.isTransitionSet()) {
+            inPendingTransaction = true;
+            if (visible) {
+                displayContent.mOpeningApps.add(this);
+                mEnteringAnimation = true;
+            } else {
+                displayContent.mClosingApps.add(this);
+                mEnteringAnimation = false;
+            }
+            if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
+                // We're launchingBehind, add the launching activity to mOpeningApps.
+                final WindowState win = getDisplayContent().findFocusedWindow();
+                if (win != null) {
+                    final ActivityRecord focusedActivity = win.mActivityRecord;
+                    if (focusedActivity != null) {
+                        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
+                                "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
+                                focusedActivity);
+
+                        // Force animation to be loaded.
+                        displayContent.mOpeningApps.add(focusedActivity);
+                    }
+                }
+            }
+            return;
+        }
+
+        commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
+        updateReportedVisibilityLocked();
+    }
+
+    boolean commitVisibility(WindowManager.LayoutParams lp,
+            boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
+
+        boolean delayed = false;
+        inPendingTransaction = false;
+        // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
+        // been set by the app now.
+        mHiddenSetFromTransferredStartingWindow = false;
+
+        // Allow for state changes and animation to be applied if:
+        // * token is transitioning visibility state
+        // * or the token was marked as hidden and is exiting before we had a chance to play the
+        // transition animation
+        // * or this is an opening app and windows are being replaced
+        // * or the token is the opening app and visible while opening task behind existing one.
+        final DisplayContent displayContent = getDisplayContent();
+        boolean visibilityChanged = false;
+        if (isHidden() == visible || (isHidden() && mIsExiting)
+                || (visible && waitingForReplacement())
+                || (visible && displayContent.mOpeningApps.contains(this)
+                && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
+            final AccessibilityController accessibilityController =
+                    mWmService.mAccessibilityController;
+            boolean changed = false;
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                    "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
+                    performLayout);
+
+            boolean runningAppAnimation = false;
+
+            if (transit != WindowManager.TRANSIT_UNSET) {
+                if (mUseTransferredAnimation) {
+                    runningAppAnimation = isReallyAnimating();
+                } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
+                    runningAppAnimation = true;
+                }
+                delayed = runningAppAnimation;
+                final WindowState window = findMainWindow();
+                if (window != null && accessibilityController != null) {
+                    accessibilityController.onAppWindowTransitionLocked(window, transit);
+                }
+                changed = true;
+            }
+
+            final int windowsCount = mChildren.size();
+            for (int i = 0; i < windowsCount; i++) {
+                final WindowState win = mChildren.get(i);
+                changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
+            }
+
+            setHidden(!visible);
+            hiddenRequested = !visible;
+            visibilityChanged = true;
+            if (!visible) {
+                stopFreezingScreen(true, true);
+            } else {
+                // If we are being set visible, and the starting window is not yet displayed,
+                // then make sure it doesn't get displayed.
+                if (startingWindow != null && !startingWindow.isDrawnLw()) {
+                    startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
+                    startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
+                }
+
+                // We are becoming visible, so better freeze the screen with the windows that are
+                // getting visible so we also wait for them.
+                forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
+            }
+
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                    "commitVisibility: %s: hidden=%b hiddenRequested=%b", this,
+                    isHidden(), hiddenRequested);
+
+            if (changed) {
+                displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
+                if (performLayout) {
+                    mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                            false /*updateInputWindows*/);
+                    mWmService.mWindowPlacerLocked.performSurfacePlacement();
+                }
+                displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
+            }
+        }
+        mUseTransferredAnimation = false;
+
+        if (isReallyAnimating()) {
+            delayed = true;
+        } else {
+            // We aren't animating anything, but exiting windows rely on the animation finished
+            // callback being called in case the ActivityRecord was pretending to be animating,
+            // which we might have done because we were in closing/opening apps list.
+            onAnimationFinished();
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
+            if ((mChildren.get(i)).isSelfOrChildAnimating()) {
+                delayed = true;
+            }
+        }
+
+        if (visibilityChanged) {
+            if (visible && !delayed) {
+                // The token was made immediately visible, there will be no entrance animation.
+                // We need to inform the client the enter animation was finished.
+                mEnteringAnimation = true;
+                mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
+                        token);
+            }
+
+            // If we're becoming visible, immediately change client visibility as well. there seem
+            // to be some edge cases where we change our visibility but client visibility never gets
+            // updated.
+            // If we're becoming invisible, update the client visibility if we are not running an
+            // animation. Otherwise, we'll update client visibility in onAnimationFinished.
+            if (visible || !isReallyAnimating()) {
+                setClientHidden(!visible);
+            }
+
+            if (!displayContent.mClosingApps.contains(this)
+                    && !displayContent.mOpeningApps.contains(this)) {
+                // The token is not closing nor opening, so even if there is an animation set, that
+                // doesn't mean that it goes through the normal app transition cycle so we have
+                // to inform the docked controller about visibility change.
+                // TODO(multi-display): notify docked divider on all displays where visibility was
+                // affected.
+                displayContent.getDockedDividerController().notifyAppVisibilityChanged();
+
+                // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
+                // will not be taken.
+                mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
+            }
+
+            // If we are hidden but there is no delay needed we immediately
+            // apply the Surface transaction so that the ActivityManager
+            // can have some guarantee on the Surface state following
+            // setting the visibility. This captures cases like dismissing
+            // the docked or pinned stack where there is no app transition.
+            //
+            // In the case of a "Null" animation, there will be
+            // no animation but there will still be a transition set.
+            // We still need to delay hiding the surface such that it
+            // can be synchronized with showing the next surface in the transition.
+            if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
+                SurfaceControl.openTransaction();
+                for (int i = mChildren.size() - 1; i >= 0; i--) {
+                    mChildren.get(i).mWinAnimator.hide("immediately hidden");
+                }
+                SurfaceControl.closeTransaction();
+            }
+        }
+
+        return delayed;
+    }
+
+    @Override
+    void setHidden(boolean hidden) {
+        super.setHidden(hidden);
+        scheduleAnimation();
+    }
+
+    @Override
+    void onAppTransitionDone() {
+        sendingToBottom = false;
+    }
+
+    /**
+     * See {@link Activity#setDisablePreviewScreenshots}.
+     */
+    void setDisablePreviewScreenshots(boolean disable) {
+        mDisablePreviewScreenshots = disable;
+    }
+
+    /**
+     * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
+     * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
+     * we can't take a snapshot for other reasons, for example, if we have a secure window.
+     *
+     * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
+     *         screenshot.
+     */
+    boolean shouldUseAppThemeSnapshot() {
+        return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
+                true /* topToBottom */);
+    }
+
+    /**
+     * Sets whether the current launch can turn the screen on.
+     * @see #currentLaunchCanTurnScreenOn()
+     */
+    void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
+        mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
+    }
+
+    /**
+     * Indicates whether the current launch can turn the screen on. This is to prevent multiple
+     * relayouts from turning the screen back on. The screen should only turn on at most
+     * once per activity resume.
+     * <p>
+     * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
+     * or {@link ActivityRecord#canTurnScreenOn} is set.
+     *
+     * @return {@code true} if the activity is ready to turn on the screen.
+     */
+    boolean currentLaunchCanTurnScreenOn() {
+        return mCurrentLaunchCanTurnScreenOn;
+    }
+
     void setState(ActivityState state, String reason) {
         if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
                         + " to:" + state + " reason:" + reason);
@@ -2510,13 +4460,63 @@
                 || state5 == mState;
     }
 
+    void destroySurfaces() {
+        destroySurfaces(false /*cleanupOnResume*/);
+    }
+
+    /**
+     * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
+     * the client has finished with them.
+     *
+     * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
+     * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
+     * others so that they are ready to be reused. If set to false (common case), destroy all
+     * surfaces that's eligible, if the app is already stopped.
+     */
+    private void destroySurfaces(boolean cleanupOnResume) {
+        boolean destroyedSomething = false;
+
+        // Copying to a different list as multiple children can be removed.
+        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
+        for (int i = children.size() - 1; i >= 0; i--) {
+            final WindowState win = children.get(i);
+            destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
+        }
+        if (destroyedSomething) {
+            final DisplayContent dc = getDisplayContent();
+            dc.assignWindowLayers(true /*setLayoutNeeded*/);
+            updateLetterboxSurface(null);
+        }
+    }
+
     void notifyAppResumed(boolean wasStopped) {
         if (getParent() == null) {
             Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
                     + appToken);
             return;
         }
-        super.notifyAppResumed(wasStopped);
+        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
+                wasStopped, this);
+        mAppStopped = false;
+        // Allow the window to turn the screen on once the app is resumed again.
+        setCurrentLaunchCanTurnScreenOn(true);
+        if (!wasStopped) {
+            destroySurfaces(true /*cleanupOnResume*/);
+        }
+    }
+
+    /**
+     * Notify that the app has stopped, and it is okay to destroy any surfaces which were
+     * keeping alive in case they were still being used.
+     */
+    void notifyAppStopped() {
+        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
+        mAppStopped = true;
+        // Reset the last saved PiP snap fraction on app stop.
+        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
+        destroySurfaces();
+        // Remove any starting window that was added for this app if they are still around.
+        removeStartingWindow();
     }
 
     void notifyUnknownVisibilityLaunched() {
@@ -3087,6 +5087,40 @@
         }
     }
 
+    void startFreezingScreen() {
+        ProtoLog.i(WM_DEBUG_ORIENTATION,
+                "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
+                appToken, isHidden(), mFreezingScreen, hiddenRequested,
+                new RuntimeException().fillInStackTrace());
+        if (!hiddenRequested) {
+            if (!mFreezingScreen) {
+                mFreezingScreen = true;
+                mWmService.registerAppFreezeListener(this);
+                mWmService.mAppsFreezingScreen++;
+                if (mWmService.mAppsFreezingScreen == 1) {
+                    mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
+                    mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
+                    mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
+                }
+            }
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                final WindowState w = mChildren.get(i);
+                w.onStartFreezingScreen();
+            }
+        }
+    }
+
+    boolean isFreezingScreen() {
+        return mFreezingScreen;
+    }
+
+    @Override
+    public void onAppFreezeTimeout() {
+        Slog.w(TAG_WM, "Force clearing freeze: " + this);
+        stopFreezingScreen(true, true);
+    }
+
     void stopFreezingScreenLocked(boolean force) {
         if (force || frozenBeforeDestroy) {
             frozenBeforeDestroy = false;
@@ -3100,6 +5134,33 @@
         }
     }
 
+    void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
+        if (!mFreezingScreen) {
+            return;
+        }
+        ProtoLog.v(WM_DEBUG_ORIENTATION,
+                "Clear freezing of %s force=%b", this, force);
+        final int count = mChildren.size();
+        boolean unfrozeWindows = false;
+        for (int i = 0; i < count; i++) {
+            final WindowState w = mChildren.get(i);
+            unfrozeWindows |= w.onStopFreezingScreen();
+        }
+        if (force || unfrozeWindows) {
+            ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
+            mFreezingScreen = false;
+            mWmService.unregisterAppFreezeListener(this);
+            mWmService.mAppsFreezingScreen--;
+            mWmService.mLastFinishedFreezeSource = this;
+        }
+        if (unfreezeSurfaceNow) {
+            if (unfrozeWindows) {
+                mWmService.mWindowPlacerLocked.performSurfacePlacement();
+            }
+            mWmService.stopFreezingDisplayLocked();
+        }
+    }
+
     void reportFullyDrawnLocked(boolean restoredFromBundle) {
         final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
             .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
@@ -3109,6 +5170,24 @@
         }
     }
 
+    void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
+        firstWindowDrawn = true;
+
+        // We now have a good window to show, remove dead placeholders
+        removeDeadWindows();
+
+        if (startingWindow != null) {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
+                    + ": first real window is shown, no animation", win.mToken);
+            // If this initial window is animating, stop it -- we will do an animation to reveal
+            // it from behind the starting window, so there is no need for it to also be doing its
+            // own stuff.
+            win.cancelAnimation();
+        }
+        removeStartingWindow();
+        updateReportedVisibilityLocked();
+    }
+
     /** Called when the windows associated app window container are drawn. */
     void onWindowsDrawn(boolean drawn, long timestampNs) {
         mDrawn = drawn;
@@ -3130,7 +5209,7 @@
 
     /** Called when the windows associated app window container are visible. */
     void onWindowsVisible() {
-        super.onWindowsVisible();
+        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
         mStackSupervisor.stopWaitingForActivityVisible(this);
         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
         if (!nowVisible) {
@@ -3142,11 +5221,197 @@
 
     /** Called when the windows associated app window container are no longer visible. */
     void onWindowsGone() {
-        super.onWindowsGone();
+        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
         nowVisible = false;
     }
 
+    @Override
+    void checkAppWindowsReadyToShow() {
+        if (allDrawn == mLastAllDrawn) {
+            return;
+        }
+
+        mLastAllDrawn = allDrawn;
+        if (!allDrawn) {
+            return;
+        }
+
+        // The token has now changed state to having all windows shown...  what to do, what to do?
+        if (mFreezingScreen) {
+            showAllWindowsLocked();
+            stopFreezingScreen(false, true);
+            ProtoLog.i(WM_DEBUG_ORIENTATION,
+                    "Setting mOrientationChangeComplete=true because wtoken %s "
+                            + "numInteresting=%d numDrawn=%d",
+                    this, mNumInterestingWindows, mNumDrawnWindows);
+            // This will set mOrientationChangeComplete and cause a pass through layout.
+            setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
+                    "checkAppWindowsReadyToShow: freezingScreen");
+        } else {
+            setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
+
+            // We can now show all of the drawn windows!
+            if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
+                showAllWindowsLocked();
+            }
+        }
+    }
+
+    /**
+     * This must be called while inside a transaction.
+     */
+    void showAllWindowsLocked() {
+        forAllWindows(windowState -> {
+            if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
+            windowState.performShowLocked();
+        }, false /* traverseTopToBottom */);
+    }
+
+    void updateReportedVisibilityLocked() {
+        if (appToken == null) {
+            return;
+        }
+
+        if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
+        final int count = mChildren.size();
+
+        mReportedVisibilityResults.reset();
+
+        for (int i = 0; i < count; i++) {
+            final WindowState win = mChildren.get(i);
+            win.updateReportedVisibility(mReportedVisibilityResults);
+        }
+
+        int numInteresting = mReportedVisibilityResults.numInteresting;
+        int numVisible = mReportedVisibilityResults.numVisible;
+        int numDrawn = mReportedVisibilityResults.numDrawn;
+        boolean nowGone = mReportedVisibilityResults.nowGone;
+
+        boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
+        boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
+        if (!nowGone) {
+            // If the app is not yet gone, then it can only become visible/drawn.
+            if (!nowDrawn) {
+                nowDrawn = reportedDrawn;
+            }
+            if (!nowVisible) {
+                nowVisible = reportedVisible;
+            }
+        }
+        if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
+                + numInteresting + " visible=" + numVisible);
+        if (nowDrawn != reportedDrawn) {
+            onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
+            reportedDrawn = nowDrawn;
+        }
+        if (nowVisible != reportedVisible) {
+            if (DEBUG_VISIBILITY) Slog.v(TAG,
+                    "Visibility changed in " + this + ": vis=" + nowVisible);
+            reportedVisible = nowVisible;
+            if (nowVisible) {
+                onWindowsVisible();
+            } else {
+                onWindowsGone();
+            }
+        }
+    }
+
+    boolean isClientHidden() {
+        return mClientHidden;
+    }
+
+    void setClientHidden(boolean hideClient) {
+        if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
+            return;
+        }
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
+                "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
+                Debug.getCallers(5));
+        mClientHidden = hideClient;
+        sendAppVisibilityToClients();
+    }
+
+    /**
+     * Updated this app token tracking states for interesting and drawn windows based on the window.
+     *
+     * @return Returns true if the input window is considered interesting and drawn while all the
+     *         windows in this app token where not considered drawn as of the last pass.
+     */
+    boolean updateDrawnWindowStates(WindowState w) {
+        w.setDrawnStateEvaluated(true /*evaluated*/);
+
+        if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
+            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
+                    + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
+        }
+
+        if (allDrawn && !mFreezingScreen) {
+            return false;
+        }
+
+        if (mLastTransactionSequence != mWmService.mTransactionSequence) {
+            mLastTransactionSequence = mWmService.mTransactionSequence;
+            mNumDrawnWindows = 0;
+            startingDisplayed = false;
+
+            // There is the main base application window, even if it is exiting, wait for it
+            mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
+        }
+
+        final WindowStateAnimator winAnimator = w.mWinAnimator;
+
+        boolean isInterestingAndDrawn = false;
+
+        if (!allDrawn && w.mightAffectAllDrawn()) {
+            if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
+                Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
+                        + ", isAnimationSet=" + isSelfAnimating());
+                if (!w.isDrawnLw()) {
+                    Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
+                            + " pv=" + w.isVisibleByPolicy()
+                            + " mDrawState=" + winAnimator.drawStateToString()
+                            + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
+                            + " a=" + isSelfAnimating());
+                }
+            }
+
+            if (w != startingWindow) {
+                if (w.isInteresting()) {
+                    // Add non-main window as interesting since the main app has already been added
+                    if (findMainWindow(false /* includeStartingApp */) != w) {
+                        mNumInterestingWindows++;
+                    }
+                    if (w.isDrawnLw()) {
+                        mNumDrawnWindows++;
+
+                        if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
+                            Slog.v(TAG, "tokenMayBeDrawn: "
+                                    + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
+                                    + " freezingScreen=" + mFreezingScreen
+                                    + " mAppFreezing=" + w.mAppFreezing);
+                        }
+
+                        isInterestingAndDrawn = true;
+                    }
+                }
+            } else if (w.isDrawnLw()) {
+                onStartingWindowDrawn(SystemClock.uptimeMillis());
+                startingDisplayed = true;
+            }
+        }
+
+        return isInterestingAndDrawn;
+    }
+
+    /** Called when the starting window for this container is drawn. */
+    private void onStartingWindowDrawn(long timestamp) {
+        synchronized (mAtmService.mGlobalLock) {
+            mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
+                    getWindowingMode(), timestamp);
+        }
+    }
+
     /**
      * Called when the key dispatching to a window associated with the app window container
      * timed-out.
@@ -3361,6 +5626,780 @@
         }
     }
 
+    void postWindowRemoveStartingWindowCleanup(WindowState win) {
+        // TODO: Something smells about the code below...Is there a better way?
+        if (startingWindow == win) {
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
+            removeStartingWindow();
+        } else if (mChildren.size() == 0) {
+            // If this is the last window and we had requested a starting transition window,
+            // well there is no point now.
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
+            mStartingData = null;
+            if (mHiddenSetFromTransferredStartingWindow) {
+                // We set the hidden state to false for the token from a transferred starting window.
+                // We now reset it back to true since the starting window was the last window in the
+                // token.
+                setHidden(true);
+            }
+        } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
+            // If this is the last window except for a starting transition window,
+            // we need to get rid of the starting transition.
+            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
+            removeStartingWindow();
+        }
+    }
+
+    void removeDeadWindows() {
+        for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
+            WindowState win = mChildren.get(winNdx);
+            if (win.mAppDied) {
+                ProtoLog.w(WM_DEBUG_ADD_REMOVE,
+                        "removeDeadWindows: %s", win);
+                // Set mDestroying, we don't want any animation or delayed removal here.
+                win.mDestroying = true;
+                // Also removes child windows.
+                win.removeIfPossible();
+            }
+        }
+    }
+
+    boolean hasWindowsAlive() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            // No need to loop through child windows as the answer should be the same as that of the
+            // parent window.
+            if (!(mChildren.get(i)).mAppDied) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void setWillReplaceWindows(boolean animate) {
+        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
+                "Marking app token %s with replacing windows.", this);
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.setWillReplaceWindow(animate);
+        }
+    }
+
+    void setWillReplaceChildWindows() {
+        ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
+                + " with replacing child windows.", this);
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.setWillReplaceChildWindows();
+        }
+    }
+
+    void clearWillReplaceWindows() {
+        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
+                "Resetting app token %s of replacing window marks.", this);
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.clearWillReplaceWindow();
+        }
+    }
+
+    void requestUpdateWallpaperIfNeeded() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            w.requestUpdateWallpaperIfNeeded();
+        }
+    }
+
+    /**
+     * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
+     *         true.
+     */
+    WindowState getTopFullscreenWindow() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            if (win != null && win.mAttrs.isFullscreen()) {
+                return win;
+            }
+        }
+        return null;
+    }
+
+    WindowState findMainWindow() {
+        return findMainWindow(true);
+    }
+
+    /**
+     * Finds the main window that either has type base application or application starting if
+     * requested.
+     *
+     * @param includeStartingApp Allow to search application-starting windows to also be returned.
+     * @return The main window of type base application or application starting if requested.
+     */
+    WindowState findMainWindow(boolean includeStartingApp) {
+        WindowState candidate = null;
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
+            final WindowState win = mChildren.get(j);
+            final int type = win.mAttrs.type;
+            // No need to loop through child window as base application and starting types can't be
+            // child windows.
+            if (type == TYPE_BASE_APPLICATION
+                    || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
+                // In cases where there are multiple windows, we prefer the non-exiting window. This
+                // happens for example when replacing windows during an activity relaunch. When
+                // constructing the animation, we want the new window, not the exiting one.
+                if (win.mAnimatingExit) {
+                    candidate = win;
+                } else {
+                    return win;
+                }
+            }
+        }
+        return candidate;
+    }
+
+    SurfaceControl getAppAnimationLayer() {
+        return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
+                : needsZBoost() ? ANIMATION_LAYER_BOOSTED
+                        : ANIMATION_LAYER_STANDARD);
+    }
+
+    @Override
+    boolean needsZBoost() {
+        return mNeedsZBoost || super.needsZBoost();
+    }
+
+    @Override
+    public SurfaceControl getAnimationLeashParent() {
+        // For transitions in the pinned stack (menu activity) we just let them occur as a child
+        // of the pinned stack.
+        // All normal app transitions take place in an animation layer which is below the pinned
+        // stack but may be above the parent stacks of the given animating apps by default. When
+        // a new hierarchical animation is enabled, we just let them occur as a child of the parent
+        // stack, i.e. the hierarchy of the surfaces is unchanged.
+        if (inPinnedWindowingMode()) {
+            return getStack().getSurfaceControl();
+        } else if (WindowManagerService.sHierarchicalAnimations) {
+            return super.getAnimationLeashParent();
+        } else {
+            return getAppAnimationLayer();
+        }
+    }
+
+
+    @VisibleForTesting
+    boolean shouldAnimate(int transit) {
+        final boolean isSplitScreenPrimary =
+                getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+        final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
+
+        // Don't animate while the task runs recents animation but only if we are in the mode
+        // where we cancel with deferred screenshot, which means that the controller has
+        // transformed the task.
+        final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
+        if (controller != null && controller.isAnimatingTask(getTask())
+                && controller.shouldDeferCancelUntilNextTransition()) {
+            return false;
+        }
+
+        // We animate always if it's not split screen primary, and only some special cases in split
+        // screen primary because it causes issues with stack clipping when we run an un-minimize
+        // animation at the same time.
+        return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
+    }
+
+    /**
+     * Creates a layer to apply crop to an animation.
+     */
+    private SurfaceControl createAnimationBoundsLayer(Transaction t) {
+        ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
+        final SurfaceControl.Builder builder = makeAnimationLeash()
+                .setParent(getAnimationLeashParent())
+                .setName(getSurfaceControl() + " - animation-bounds");
+        final SurfaceControl boundsLayer = builder.build();
+        t.show(boundsLayer);
+        return boundsLayer;
+    }
+
+    boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
+            boolean isVoiceInteraction) {
+
+        if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
+                    "applyAnimation: transition animation is disabled or skipped. "
+                            + "atoken=%s", this);
+            cancelAnimation();
+            return false;
+        }
+
+        // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
+        // to animate and it can cause strange artifacts when we unfreeze the display if some
+        // different animation is running.
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
+        if (okToAnimate()) {
+            final AnimationAdapter adapter;
+            AnimationAdapter thumbnailAdapter = null;
+
+            final int appStackClipMode =
+                    getDisplayContent().mAppTransition.getAppStackClipMode();
+
+            // Separate position and size for use in animators.
+            mTmpRect.set(getAnimationBounds(appStackClipMode));
+            mTmpPoint.set(mTmpRect.left, mTmpRect.top);
+            mTmpRect.offsetTo(0, 0);
+
+            final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
+                    && getDisplayContent().mChangingApps.contains(this);
+
+            // Delaying animation start isn't compatible with remote animations at all.
+            if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
+                    && !mSurfaceAnimator.isAnimationStartDelayed()) {
+                RemoteAnimationController.RemoteAnimationRecord adapters =
+                        getDisplayContent().mAppTransition.getRemoteAnimationController()
+                                .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
+                                        (isChanging ? mTransitStartRect : null));
+                adapter = adapters.mAdapter;
+                thumbnailAdapter = adapters.mThumbnailAdapter;
+            } else if (isChanging) {
+                final float durationScale = mWmService.getTransitionAnimationScaleLocked();
+                mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
+                adapter = new LocalAnimationAdapter(
+                        new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
+                                getDisplayContent().getDisplayInfo(), durationScale,
+                                true /* isAppAnimation */, false /* isThumbnail */),
+                        mWmService.mSurfaceAnimationRunner);
+                if (mThumbnail != null) {
+                    thumbnailAdapter = new LocalAnimationAdapter(
+                            new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
+                                    getDisplayContent().getDisplayInfo(), durationScale,
+                                    true /* isAppAnimation */, true /* isThumbnail */),
+                            mWmService.mSurfaceAnimationRunner);
+                }
+                mTransit = transit;
+                mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
+            } else {
+                mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
+
+                final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
+                if (a != null) {
+                    // Only apply corner radius to animation if we're not in multi window mode.
+                    // We don't want rounded corners when in pip or split screen.
+                    final float windowCornerRadius = !inMultiWindowMode()
+                            ? getDisplayContent().getWindowCornerRadius()
+                            : 0;
+                    adapter = new LocalAnimationAdapter(
+                            new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
+                                    getDisplayContent().mAppTransition.canSkipFirstFrame(),
+                                    appStackClipMode,
+                                    true /* isAppAnimation */,
+                                    windowCornerRadius),
+                            mWmService.mSurfaceAnimationRunner);
+                    if (a.getZAdjustment() == Animation.ZORDER_TOP) {
+                        mNeedsZBoost = true;
+                    }
+                    mTransit = transit;
+                    mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
+                } else {
+                    adapter = null;
+                }
+            }
+            if (adapter != null) {
+                startAnimation(getPendingTransaction(), adapter, !isVisible());
+                if (adapter.getShowWallpaper()) {
+                    mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+                }
+                if (thumbnailAdapter != null) {
+                    mThumbnail.startAnimation(
+                            getPendingTransaction(), thumbnailAdapter, !isVisible());
+                }
+            }
+        } else {
+            cancelAnimation();
+        }
+        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+
+        return isReallyAnimating();
+    }
+
+    private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
+            boolean isVoiceInteraction) {
+        final DisplayContent displayContent = getTask().getDisplayContent();
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final int width = displayInfo.appWidth;
+        final int height = displayInfo.appHeight;
+        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
+                "applyAnimation: atoken=%s", this);
+
+        // Determine the visible rect to calculate the thumbnail clip
+        final WindowState win = findMainWindow();
+        final Rect frame = new Rect(0, 0, width, height);
+        final Rect displayFrame = new Rect(0, 0,
+                displayInfo.logicalWidth, displayInfo.logicalHeight);
+        final Rect insets = new Rect();
+        final Rect stableInsets = new Rect();
+        Rect surfaceInsets = null;
+        final boolean freeform = win != null && win.inFreeformWindowingMode();
+        if (win != null) {
+            // Containing frame will usually cover the whole screen, including dialog windows.
+            // For freeform workspace windows it will not cover the whole screen and it also
+            // won't exactly match the final freeform window frame (e.g. when overlapping with
+            // the status bar). In that case we need to use the final frame.
+            if (freeform) {
+                frame.set(win.getFrameLw());
+            } else if (win.isLetterboxedAppWindow()) {
+                frame.set(getTask().getBounds());
+            } else if (win.isDockedResizing()) {
+                // If we are animating while docked resizing, then use the stack bounds as the
+                // animation target (which will be different than the task bounds)
+                frame.set(getTask().getParent().getBounds());
+            } else {
+                frame.set(win.getContainingFrame());
+            }
+            surfaceInsets = win.getAttrs().surfaceInsets;
+            // XXX(b/72757033): These are insets relative to the window frame, but we're really
+            // interested in the insets relative to the frame we chose in the if-blocks above.
+            win.getContentInsets(insets);
+            win.getStableInsets(stableInsets);
+        }
+
+        if (mLaunchTaskBehind) {
+            // Differentiate the two animations. This one which is briefly on the screen
+            // gets the !enter animation, and the other activity which remains on the
+            // screen gets the enter animation. Both appear in the mOpeningApps set.
+            enter = false;
+        }
+        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
+                "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
+                        + "surfaceInsets=%s",
+                AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
+        final Configuration displayConfig = displayContent.getConfiguration();
+        final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
+                displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
+                surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
+        if (a != null) {
+            if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
+            final int containingWidth = frame.width();
+            final int containingHeight = frame.height();
+            a.initialize(containingWidth, containingHeight, width, height);
+            a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
+        }
+        return a;
+    }
+
+    @Override
+    public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+        return mAnimatingActivityRegistry != null
+                && mAnimatingActivityRegistry.notifyAboutToFinish(
+                this, endDeferFinishCallback);
+    }
+
+    private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
+        if (mWmService.mDisableTransitionAnimation
+                || !isVisible()
+                || getDisplayContent().mAppTransition.isTransitionSet()
+                || getSurfaceControl() == null) {
+            return false;
+        }
+        // Only do an animation into and out-of freeform mode for now. Other mode
+        // transition animations are currently handled by system-ui.
+        return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
+    }
+
+    boolean isWaitingForTransitionStart() {
+        final DisplayContent dc = getDisplayContent();
+        // TODO: Test for null can be removed once unification is done.
+        if (dc == null) return false;
+        return dc.mAppTransition.isTransitionSet()
+                && (dc.mOpeningApps.contains(this)
+                || dc.mClosingApps.contains(this)
+                || dc.mChangingApps.contains(this));
+    }
+
+    /**
+     * Initializes a change transition. Because the app is visible already, there is a small period
+     * of time where the user can see the app content/window update before the transition starts.
+     * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
+     * "freezes" the location/crop until the transition starts.
+     * <p>
+     * Here's a walk-through of the process:
+     * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
+     * 2. Set the temporary leash's position/crop to the current state.
+     * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
+     * 4. Once the transition is ready, it will reparent the app to the animation leash.
+     * 5. Detach the interim-change-leash.
+     */
+    private void initializeChangeTransition(Rect startBounds) {
+        mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+                false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
+        mDisplayContent.mChangingApps.add(this);
+        mTransitStartRect.set(startBounds);
+
+        final SurfaceControl.Builder builder = makeAnimationLeash()
+                .setParent(getAnimationLeashParent())
+                .setName(getSurfaceControl() + " - interim-change-leash");
+        mTransitChangeLeash = builder.build();
+        Transaction t = getPendingTransaction();
+        t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
+        t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
+        t.show(mTransitChangeLeash);
+        t.reparent(getSurfaceControl(), mTransitChangeLeash);
+        onAnimationLeashCreated(t, mTransitChangeLeash);
+
+        // Skip creating snapshot if this transition is controlled by a remote animator which
+        // doesn't need it.
+        ArraySet<Integer> activityTypes = new ArraySet<>();
+        activityTypes.add(getActivityType());
+        RemoteAnimationAdapter adapter =
+                mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
+                        this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
+        if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
+            return;
+        }
+
+        Task task = getTask();
+        if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
+            SurfaceControl.ScreenshotGraphicBuffer snapshot =
+                    mWmService.mTaskSnapshotController.createTaskSnapshot(
+                            task, 1 /* scaleFraction */);
+            if (snapshot != null) {
+                mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
+                        snapshot.getGraphicBuffer(), true /* relative */);
+            }
+        }
+    }
+
+    @Override
+    public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
+        // The leash is parented to the animation layer. We need to preserve the z-order by using
+        // the prefix order index, but we boost if necessary.
+        int layer = 0;
+        if (!inPinnedWindowingMode()) {
+            layer = getPrefixOrderIndex();
+        } else {
+            // Pinned stacks have animations take place within themselves rather than an animation
+            // layer so we need to preserve the order relative to the stack (e.g. the order of our
+            // task/parent).
+            layer = getParent().getPrefixOrderIndex();
+        }
+
+        if (mNeedsZBoost) {
+            layer += Z_BOOST_BASE;
+        }
+        if (!mNeedsAnimationBoundsLayer) {
+            t.setLayer(leash, layer);
+        }
+
+        final DisplayContent dc = getDisplayContent();
+        dc.assignStackOrdering();
+
+        if (leash == mTransitChangeLeash) {
+            // This is a temporary state so skip any animation notifications
+            return;
+        } else if (mTransitChangeLeash != null) {
+            // unparent mTransitChangeLeash for clean-up
+            clearChangeLeash(t, false /* cancel */);
+        }
+
+        if (mAnimatingActivityRegistry != null) {
+            mAnimatingActivityRegistry.notifyStarting(this);
+        }
+
+        // If the animation needs to be cropped then an animation bounds layer is created as a child
+        // of the pinned stack or animation layer. The leash is then reparented to this new layer.
+        if (mNeedsAnimationBoundsLayer) {
+            mTmpRect.setEmpty();
+            final Task task = getTask();
+            if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
+                    getTransit(), task)) {
+                task.getBounds(mTmpRect);
+            } else {
+                final TaskStack stack = getStack();
+                if (stack == null) {
+                    return;
+                }
+                // Set clip rect to stack bounds.
+                stack.getBounds(mTmpRect);
+            }
+            mAnimationBoundsLayer = createAnimationBoundsLayer(t);
+
+            // Crop to stack bounds.
+            t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
+            t.setLayer(mAnimationBoundsLayer, layer);
+
+            // Reparent leash to animation bounds layer.
+            t.reparent(leash, mAnimationBoundsLayer);
+        }
+    }
+
+    @Override
+    void prepareSurfaces() {
+        // isSelfAnimating also returns true when we are about to start a transition, so we need
+        // to check super here.
+        final boolean reallyAnimating = super.isSelfAnimating();
+        final boolean show = !isHidden() || reallyAnimating;
+
+        if (mSurfaceControl != null) {
+            if (show && !mLastSurfaceShowing) {
+                getPendingTransaction().show(mSurfaceControl);
+            } else if (!show && mLastSurfaceShowing) {
+                getPendingTransaction().hide(mSurfaceControl);
+            }
+        }
+        if (mThumbnail != null) {
+            mThumbnail.setShowing(getPendingTransaction(), show);
+        }
+        mLastSurfaceShowing = show;
+        super.prepareSurfaces();
+    }
+
+    /**
+     * @return Whether our {@link #getSurfaceControl} is currently showing.
+     */
+    boolean isSurfaceShowing() {
+        return mLastSurfaceShowing;
+    }
+
+    boolean isInChangeTransition() {
+        return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
+    }
+
+    void attachThumbnailAnimation() {
+        if (!isReallyAnimating()) {
+            return;
+        }
+        final int taskId = getTask().mTaskId;
+        final GraphicBuffer thumbnailHeader =
+                getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
+        if (thumbnailHeader == null) {
+            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId);
+            return;
+        }
+        clearThumbnail();
+        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
+                this, thumbnailHeader);
+        mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
+    }
+
+    /**
+     * Attaches a surface with a thumbnail for the
+     * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
+     */
+    void attachCrossProfileAppsThumbnailAnimation() {
+        if (!isReallyAnimating()) {
+            return;
+        }
+        clearThumbnail();
+
+        final WindowState win = findMainWindow();
+        if (win == null) {
+            return;
+        }
+        final Rect frame = win.getFrameLw();
+        final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
+                ? R.drawable.ic_account_circle
+                : R.drawable.ic_corp_badge;
+        final GraphicBuffer thumbnail =
+                getDisplayContent().mAppTransition
+                        .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
+        if (thumbnail == null) {
+            return;
+        }
+        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
+                getPendingTransaction(), this, thumbnail);
+        final Animation animation =
+                getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
+                        win.getFrameLw());
+        mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
+                frame.top));
+    }
+
+    private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
+        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+
+        // If this is a multi-window scenario, we use the windows frame as
+        // destination of the thumbnail header animation. If this is a full screen
+        // window scenario, we use the whole display as the target.
+        WindowState win = findMainWindow();
+        Rect appRect = win != null ? win.getContentFrameLw() :
+                new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
+        final Rect insets = win != null ? win.getContentInsets() : null;
+        final Configuration displayConfig = mDisplayContent.getConfiguration();
+        return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
+                appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
+                displayConfig.orientation);
+    }
+
+    @Override
+    boolean isAppAnimating() {
+        return isSelfAnimating();
+    }
+
+    @Override
+    boolean isSelfAnimating() {
+        // If we are about to start a transition, we also need to be considered animating.
+        return isWaitingForTransitionStart() || isReallyAnimating();
+    }
+
+    @Override
+    public void onAnimationLeashLost(Transaction t) {
+        super.onAnimationLeashLost(t);
+        if (mAnimationBoundsLayer != null) {
+            t.remove(mAnimationBoundsLayer);
+            mAnimationBoundsLayer = null;
+        }
+
+        if (mAnimatingActivityRegistry != null) {
+            mAnimatingActivityRegistry.notifyFinished(this);
+        }
+    }
+
+    @Override
+    protected void onAnimationFinished() {
+        super.onAnimationFinished();
+
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
+        mTransit = TRANSIT_UNSET;
+        mTransitFlags = 0;
+        mNeedsZBoost = false;
+        mNeedsAnimationBoundsLayer = false;
+
+        setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
+                "AppWindowToken");
+
+        clearThumbnail();
+        setClientHidden(isHidden() && hiddenRequested);
+
+        getDisplayContent().computeImeTargetIfNeeded(this);
+
+        if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
+                + ": reportedVisible=" + reportedVisible
+                + " okToDisplay=" + okToDisplay()
+                + " okToAnimate=" + okToAnimate()
+                + " startingDisplayed=" + startingDisplayed);
+
+        // clean up thumbnail window
+        if (mThumbnail != null) {
+            mThumbnail.destroy();
+            mThumbnail = null;
+        }
+
+        // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
+        // traverse the copy.
+        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
+        children.forEach(WindowState::onExitAnimationDone);
+
+        getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
+        scheduleAnimation();
+
+        if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
+                || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
+            // If all activities are already idle or there is an activity that must be
+            // stopped immediately after visible, then we now need to make sure we perform
+            // the full stop of this activity. This is because we won't do that while they are still
+            // waiting for the animation to finish.
+            if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
+                mAtmService.mStackSupervisor.scheduleIdleLocked();
+            }
+        } else {
+            // Instead of doing the full stop routine here, let's just hide any activities
+            // we now can, and let them stop when the normal idle happens.
+            mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
+                    false /* remove */, true /* processPausingActivities */);
+        }
+        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+    }
+
+    /**
+     * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
+     *                            to another leash.
+     */
+    private void clearChangeLeash(Transaction t, boolean cancel) {
+        if (mTransitChangeLeash == null) {
+            return;
+        }
+        if (cancel) {
+            clearThumbnail();
+            SurfaceControl sc = getSurfaceControl();
+            SurfaceControl parentSc = getParentSurfaceControl();
+            // Don't reparent if surface is getting destroyed
+            if (parentSc != null && sc != null) {
+                t.reparent(sc, getParentSurfaceControl());
+            }
+        }
+        t.hide(mTransitChangeLeash);
+        t.remove(mTransitChangeLeash);
+        mTransitChangeLeash = null;
+        if (cancel) {
+            onAnimationLeashLost(t);
+        }
+    }
+
+    void clearAnimatingFlags() {
+        boolean wallpaperMightChange = false;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = mChildren.get(i);
+            wallpaperMightChange |= win.clearAnimatingFlags();
+        }
+        if (wallpaperMightChange) {
+            requestUpdateWallpaperIfNeeded();
+        }
+    }
+
+    /**
+     * @return True if and only if we are actually running an animation. Note that
+     *         {@link #isSelfAnimating} also returns true if we are waiting for an animation to
+     *         start.
+     */
+    private boolean isReallyAnimating() {
+        return super.isSelfAnimating();
+    }
+
+    @Override
+    void cancelAnimation() {
+        cancelAnimationOnly();
+        clearThumbnail();
+        clearChangeLeash(getPendingTransaction(), true /* cancel */);
+    }
+
+    /**
+     * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
+     * or interim leashes.
+     * <p>
+     * Used when canceling in preparation for starting a new animation.
+     */
+    void cancelAnimationOnly() {
+        super.cancelAnimation();
+    }
+
+    @VisibleForTesting
+    AppWindowThumbnail getThumbnail() {
+        return mThumbnail;
+    }
+
+    private void clearThumbnail() {
+        if (mThumbnail == null) {
+            return;
+        }
+        mThumbnail.destroy();
+        mThumbnail = null;
+    }
+
+    public int getTransit() {
+        return mTransit;
+    }
+
+    int getTransitFlags() {
+        return mTransitFlags;
+    }
+
+    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
+        mRemoteAnimationDefinition = definition;
+    }
+
+    RemoteAnimationDefinition getRemoteAnimationDefinition() {
+        return mRemoteAnimationDefinition;
+    }
+
     void setRequestedOrientation(int requestedOrientation) {
         setOrientation(requestedOrientation, mayFreezeScreenLocked());
         mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
@@ -3380,6 +6419,49 @@
         }
     }
 
+    void reportDescendantOrientationChangeIfNeeded() {
+        // Orientation request is exposed only when we're visible. Therefore visibility change
+        // will change requested orientation. Notify upward the hierarchy ladder to adjust
+        // configuration. This is important to cases where activities with incompatible
+        // orientations launch, or user goes back from an activity of bi-orientation to an
+        // activity with specified orientation.
+        if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
+            return;
+        }
+
+        final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
+        onDescendantOrientationChanged(freezeToken, this);
+    }
+
+    /**
+     * We override because this class doesn't want its children affecting its reported orientation
+     * in anyway.
+     */
+    @Override
+    int getOrientation(int candidate) {
+        if (candidate == SCREEN_ORIENTATION_BEHIND) {
+            // Allow app to specify orientation regardless of its visibility state if the current
+            // candidate want us to use orientation behind. I.e. the visible app on-top of this one
+            // wants us to use the orientation of the app behind it.
+            return mOrientation;
+        }
+
+        // The {@link ActivityRecord} should only specify an orientation when it is not closing or
+        // going to the bottom. Allowing closing {@link ActivityRecord} to participate can lead to
+        // an Activity in another task being started in the wrong orientation during the transition.
+        if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
+                && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
+            return mOrientation;
+        }
+
+        return SCREEN_ORIENTATION_UNSET;
+    }
+
+    /** Returns the app's preferred orientation regardless of its currently visibility state. */
+    int getRequestedOrientation() {
+        return mOrientation;
+    }
+
     /**
      * Set the last reported global configuration to the client. Should be called whenever a new
      * global configuration is sent to the client for this activity.
@@ -3479,6 +6561,10 @@
                 && !mAtmService.mForceResizableActivities;
     }
 
+    boolean hasSizeCompatBounds() {
+        return mSizeCompatBounds != null;
+    }
+
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
     private void updateOverrideConfiguration() {
         final Configuration overrideConfig = mTmpConfig;
@@ -3535,6 +6621,22 @@
     }
 
     @Override
+    public boolean matchParentBounds() {
+        if (super.matchParentBounds()) {
+            return true;
+        }
+        // An activity in size compatibility mode may have override bounds which equals to its
+        // parent bounds, so the exact bounds should also be checked.
+        final WindowContainer parent = getParent();
+        return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
+    }
+
+    @Override
+    float getSizeCompatScale() {
+        return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
+    }
+
+    @Override
     void resolveOverrideConfiguration(Configuration newParentConfiguration) {
         if (mCompatDisplayInsets != null) {
             resolveSizeCompatModeConfiguration(newParentConfiguration);
@@ -3630,7 +6732,7 @@
                 mCompatDisplayInsets);
 
         // The horizontal inset included in width is not needed if the activity cannot fill the
-        // parent, because the offset will be applied by {@link AppWindowToken#mSizeCompatBounds}.
+        // parent, because the offset will be applied by {@link ActivityRecord#mSizeCompatBounds}.
         final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
         final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
         if (resolvedBounds.width() < parentAppBounds.width()) {
@@ -3644,9 +6746,100 @@
     }
 
     @Override
+    public Rect getBounds() {
+        if (mSizeCompatBounds != null) {
+            return mSizeCompatBounds;
+        }
+        return super.getBounds();
+    }
+
+    @Override
+    Rect getDisplayedBounds() {
+        final Task task = getTask();
+        if (task != null) {
+            final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
+            if (!overrideDisplayedBounds.isEmpty()) {
+                return overrideDisplayedBounds;
+            }
+        }
+        return getBounds();
+    }
+
+    @VisibleForTesting
+    Rect getAnimationBounds(int appStackClipMode) {
+        if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
+            // Using the stack bounds here effectively applies the clipping before animation.
+            return getStack().getBounds();
+        }
+        // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
+        // included in the animation.
+        return getTask() != null ? getTask().getBounds() : getBounds();
+    }
+
+    /**
+     * Calculates the scale and offset to horizontal center the size compatibility bounds into the
+     * region which is available to application.
+     */
+    private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
+        final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
+        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
+        final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
+        final Rect appBounds = getWindowConfiguration().getAppBounds();
+        final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
+        final float contentW = contentBounds.width();
+        final float contentH = contentBounds.height();
+        final float viewportW = viewportBounds.width();
+        final float viewportH = viewportBounds.height();
+        // Only allow to scale down.
+        mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
+                ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
+        final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
+                + viewportBounds.left;
+
+        if (mSizeCompatBounds == null) {
+            mSizeCompatBounds = new Rect();
+        }
+        mSizeCompatBounds.set(contentBounds);
+        mSizeCompatBounds.offsetTo(0, 0);
+        mSizeCompatBounds.scale(mSizeCompatScale);
+        // Ensure to align the top with the parent.
+        mSizeCompatBounds.top = parentBounds.top;
+        // The decor inset is included in height.
+        mSizeCompatBounds.bottom += viewportBounds.top;
+        mSizeCompatBounds.left += offsetX;
+        mSizeCompatBounds.right += offsetX;
+    }
+
+    @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
+        final int prevWinMode = getWindowingMode();
+        mTmpPrevBounds.set(getBounds());
         super.onConfigurationChanged(newParentConfig);
 
+        final Task task = getTask();
+        final Rect overrideBounds = getResolvedOverrideBounds();
+        if (task != null && !overrideBounds.isEmpty()
+                // If the changes come from change-listener, the incoming parent configuration is
+                // still the old one. Make sure their orientations are the same to reduce computing
+                // the compatibility bounds for the intermediate state.
+                && (task.mTaskRecord == null || task.mTaskRecord
+                .getConfiguration().orientation == newParentConfig.orientation)) {
+            final Rect taskBounds = task.getBounds();
+            // Since we only center the activity horizontally, if only the fixed height is smaller
+            // than its container, the override bounds don't need to take effect.
+            if ((overrideBounds.width() != taskBounds.width()
+                    || overrideBounds.height() > taskBounds.height())) {
+                calculateCompatBoundsTransformation(newParentConfig);
+                updateSurfacePosition();
+            } else if (mSizeCompatBounds != null) {
+                mSizeCompatBounds = null;
+                mSizeCompatScale = 1f;
+                updateSurfacePosition();
+            }
+        }
+
+        adjustPinnedStackAndInitChangeTransitionIfNeeded(prevWinMode, getWindowingMode());
+
         // Configuration's equality doesn't consider seq so if only seq number changes in resolved
         // override configuration. Therefore ConfigurationContainer doesn't change merged override
         // configuration, but it's used to push configuration changes so explicitly update that.
@@ -3679,6 +6872,37 @@
         }
     }
 
+    private void adjustPinnedStackAndInitChangeTransitionIfNeeded(int prevWinMode, int winMode) {
+        if (prevWinMode == winMode || mDisplayContent == null) {
+            return;
+        }
+
+        if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
+                && !isHidden()) {
+            // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
+            // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
+            final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+            if (pinnedStack != null) {
+                final Rect stackBounds;
+                if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
+                    // We are animating the bounds, use the pre-animation bounds to save the snap
+                    // fraction
+                    stackBounds = pinnedStack.mPreAnimationBounds;
+                } else {
+                    // We skip the animation if the fullscreen configuration is not compatible, so
+                    // use the current bounds to calculate the saved snap fraction instead
+                    // (see PinnedActivityStack.skipResizeAnimation())
+                    stackBounds = mTmpRect;
+                    pinnedStack.getBounds(stackBounds);
+                }
+                mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
+                        mActivityComponent, stackBounds);
+            }
+        } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
+            initializeChangeTransition(mTmpPrevBounds);
+        }
+    }
+
     /** Returns true if the configuration is compatible with this activity. */
     boolean isConfigurationCompatible(Configuration config) {
         final int orientation = getRequestedOrientation();
@@ -4344,14 +7568,13 @@
         return info.applicationInfo.uid;
     }
 
-    @Override
     int getPid() {
         return app != null ? app.getPid() : 0;
     }
 
     /**
      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
-     * {@link AppWindowToken#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
+     * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
      * should be visible depending on Keyguard state
      *
      * @return true if the screen can be turned on, false otherwise.
@@ -4365,6 +7588,14 @@
                 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
     }
 
+    void setTurnScreenOn(boolean turnScreenOn) {
+        mTurnScreenOn = turnScreenOn;
+    }
+
+    boolean getTurnScreenOnFlag() {
+        return mTurnScreenOn;
+    }
+
     /**
      * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
      * process are allowed to be resumed.
@@ -4431,7 +7662,7 @@
      * {@code ActivityRecordProto} is the outer-most proto data.
      */
     void writeToProto(ProtoOutputStream proto) {
-        super.writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
+        writeToProto(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
         writeIdentifierToProto(proto, IDENTIFIER);
         proto.write(STATE, mState.toString());
         proto.write(VISIBLE, visible);
@@ -4449,6 +7680,65 @@
     }
 
     /**
+     * Copied from old AppWindowToken.
+     */
+    @Override
+    public void writeToProto(ProtoOutputStream proto, long fieldId,
+            @WindowTraceLogLevel int logLevel) {
+        // Critical log level logs only visible elements to mitigate performance overheard
+        if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
+            return;
+        }
+
+        final long token = proto.start(fieldId);
+        writeNameToProto(proto, NAME);
+        super.writeToProto(proto, WINDOW_TOKEN, logLevel);
+        proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
+        proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
+        proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
+        if (mThumbnail != null){
+            mThumbnail.writeToProto(proto, THUMBNAIL);
+        }
+        proto.write(FILLS_PARENT, mOccludesParent);
+        proto.write(APP_STOPPED, mAppStopped);
+        proto.write(HIDDEN_REQUESTED, hiddenRequested);
+        proto.write(CLIENT_HIDDEN, mClientHidden);
+        proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
+        proto.write(REPORTED_DRAWN, reportedDrawn);
+        proto.write(REPORTED_VISIBLE, reportedVisible);
+        proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
+        proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
+        proto.write(ALL_DRAWN, allDrawn);
+        proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
+        proto.write(REMOVED, removed);
+        if (startingWindow != null) {
+            startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
+        }
+        proto.write(STARTING_DISPLAYED, startingDisplayed);
+        proto.write(STARTING_MOVED, startingMoved);
+        proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
+                mHiddenSetFromTransferredStartingWindow);
+        for (Rect bounds : mFrozenBounds) {
+            bounds.writeToProto(proto, FROZEN_BOUNDS);
+        }
+        proto.end(token);
+    }
+
+    void writeNameToProto(ProtoOutputStream proto, long fieldId) {
+        if (appToken != null) {
+            proto.write(fieldId, appToken.getName());
+        }
+    }
+
+    void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        proto.write(HASH_CODE, System.identityHashCode(this));
+        proto.write(USER_ID, mUserId);
+        proto.write(TITLE, intent.getComponent().flattenToShortString());
+        proto.end(token);
+    }
+
+    /**
      * The precomputed insets of the display in each rotation. This is used to make the size
      * compatibility mode activity compute the configuration without relying on its current display.
      */
@@ -4501,4 +7791,14 @@
                     isLandscape ? shortSide : longSide);
         }
     }
+
+    private static class AppSaturationInfo {
+        float[] mMatrix = new float[9];
+        float[] mTranslation = new float[3];
+
+        void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
+            System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
+            System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index ca74196..887ece5 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1169,7 +1169,8 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage)
+        // TODO moltmann b/136595429: Set featureId from caller
+        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage, /* featureId */ null)
                 != AppOpsManager.MODE_ALLOWED) {
             if (!ignoreTargetSecurity) {
                 return ACTIVITY_RESTRICTION_APPOP;
@@ -1212,7 +1213,8 @@
             return ACTIVITY_RESTRICTION_NONE;
         }
 
-        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage)
+        // TODO moltmann b/136595429: Set componentId from caller
+        if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage, /* featureId */ null)
                 != AppOpsManager.MODE_ALLOWED) {
             return ACTIVITY_RESTRICTION_APPOP;
         }
@@ -2084,7 +2086,6 @@
         final TaskRecord task = r.getTaskRecord();
         final ActivityStack stack = task.getStack();
 
-        r.mLaunchTaskBehind = false;
         mRecentTasks.add(task);
         mService.getTaskChangeNotificationController().notifyTaskStackChanged();
         stack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
@@ -2254,7 +2255,7 @@
             pw.print(" #"); pw.print(i); pw.print(": ");
             pw.println(r);
             if (full) {
-                r.dump(pw, innerPrefix);
+                r.dump(pw, innerPrefix, true /* dumpAll */);
             } else if (complete) {
                 // Complete + brief == give a summary.  Isn't that obvious?!?
                 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 6ee64f3..63cec1a 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -506,7 +506,7 @@
         if (mLastHomeActivityStartRecord != null) {
             pw.print(prefix);
             pw.println("mLastHomeActivityStartRecord:");
-            mLastHomeActivityStartRecord.dump(pw, prefix + "  ");
+            mLastHomeActivityStartRecord.dump(pw, prefix + "  ", true /* dumpAll */);
         }
 
         final boolean dumpPackagePresent = dumpPackage != null;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 1a80006..2ac681c 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1834,7 +1834,9 @@
      */
     private void complyActivityFlags(TaskRecord targetTask, ActivityRecord reusedActivity) {
         ActivityRecord targetTaskTop = targetTask.getTopActivity();
-        if (reusedActivity != null && (mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+        final boolean resetTask =
+                reusedActivity != null && (mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0;
+        if (resetTask) {
             targetTaskTop = mTargetStack.resetTaskIfNeededLocked(targetTaskTop, mStartActivity);
         }
 
@@ -1907,14 +1909,17 @@
                 mAddingToTask = true;
             }
         } else if (mStartActivity.mActivityComponent.equals(targetTask.realActivity)) {
-            // In this case the top activity on the task is the same as the one being launched,
-            // so we take that as a request to bring the task to the foreground. If the top
-            // activity in the task is the root activity, deliver this new intent to it if it
-            // desires.
-            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
-                    || LAUNCH_SINGLE_TOP == mLaunchMode)
-                    && targetTaskTop.mActivityComponent.equals(
-                    mStartActivity.mActivityComponent) && mStartActivity.resultTo == null) {
+            if (targetTask == mInTask) {
+                // In this case we are bringing up an existing activity from a recent task. We
+                // don't need to add a new activity instance on top.
+            } else if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
+                            || LAUNCH_SINGLE_TOP == mLaunchMode)
+                    && targetTaskTop.mActivityComponent.equals(mStartActivity.mActivityComponent)
+                    && mStartActivity.resultTo == null) {
+                // In this case the top activity on the task is the same as the one being launched,
+                // so we take that as a request to bring the task to the foreground. If the top
+                // activity in the task is the root activity, deliver this new intent to it if it
+                // desires.
                 if (targetTaskTop.isRootOfTask()) {
                     targetTaskTop.getTaskRecord().setIntent(mStartActivity);
                 }
@@ -1926,7 +1931,7 @@
             } else if (reusedActivity == null) {
                 mAddingToTask = true;
             }
-        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
+        } else if (!resetTask) {
             // In this case an activity is being launched in to an existing task, without
             // resetting that task. This is typically the situation of launching an activity
             // from a notification or shortcut. We want to place the new activity on top of the
@@ -2324,9 +2329,9 @@
                     intentActivity.setTaskToAffiliateWith(mSourceRecord.getTaskRecord());
                 }
 
-                final ActivityStack launchStack = getLaunchStack(
-                        mStartActivity, mLaunchFlags, mStartActivity.getTaskRecord(), mOptions);
                 final TaskRecord intentTask = intentActivity.getTaskRecord();
+                final ActivityStack launchStack =
+                        getLaunchStack(mStartActivity, mLaunchFlags, intentTask, mOptions);
                 if (launchStack == null || launchStack == mTargetStack) {
                     // We only want to move to the front, if we aren't going to launch on a
                     // different stack. If we launch on a different stack, we will put the
@@ -2370,9 +2375,12 @@
                             REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                             "reparentingHome");
                     mMovedToFront = true;
-                } else if (launchStack.topTask() == null) {
+                }
+
+                if (launchStack.topTask() == null) {
                     // The task does not need to be reparented to the launch stack. Remove the
                     // launch stack if there is no activity in it.
+                    Slog.w(TAG, "Removing an empty stack: " + launchStack);
                     launchStack.remove();
                 }
 
@@ -2841,12 +2849,12 @@
         if (r != null) {
             pw.print(prefix);
             pw.println("mLastStartActivityRecord:");
-            r.dump(pw, prefix + "  ");
+            r.dump(pw, prefix + "  ", true /* dumpAll */);
         }
         if (mStartActivity != null) {
             pw.print(prefix);
             pw.println("mStartActivity:");
-            mStartActivity.dump(pw, prefix + "  ");
+            mStartActivity.dump(pw, prefix + "  ", true /* dumpAll */);
         }
         if (mIntent != null) {
             pw.print(prefix);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 20113a6..14df505 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -886,7 +886,7 @@
 
     boolean hasSystemAlertWindowPermission(int callingUid, int callingPid, String callingPackage) {
         final int mode = getAppOpsService().noteOperation(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
-                callingUid, callingPackage);
+                callingUid, callingPackage, /* featureId */ null);
         if (mode == AppOpsManager.MODE_DEFAULT) {
             return checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, callingPid, callingUid)
                     == PERMISSION_GRANTED;
@@ -4984,7 +4984,7 @@
                 pw.println("(not running)");
             }
             if (dumpAll) {
-                r.dump(pw, innerPrefix);
+                r.dump(pw, innerPrefix, true /* dumpAll */);
             }
         }
         if (appThread != null) {
diff --git a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java b/services/core/java/com/android/server/wm/AnimatingActivityRegistry.java
similarity index 72%
rename from services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
rename to services/core/java/com/android/server/wm/AnimatingActivityRegistry.java
index 9c00d1a..18ec96c 100644
--- a/services/core/java/com/android/server/wm/AnimatingAppWindowTokenRegistry.java
+++ b/services/core/java/com/android/server/wm/AnimatingActivityRegistry.java
@@ -23,55 +23,55 @@
 import java.util.ArrayList;
 
 /**
- * Keeps track of all {@link AppWindowToken} that are animating and makes sure all animations are
+ * Keeps track of all {@link ActivityRecord} that are animating and makes sure all animations are
  * finished at the same time such that we don't run into issues with z-ordering: An activity A
  * that has a shorter animation that is above another activity B with a longer animation in the same
  * task, the animation layer would put the B on top of A, but from the hierarchy, A needs to be on
  * top of B. Thus, we defer reparenting A to the original hierarchy such that it stays on top of B
  * until B finishes animating.
  */
-class AnimatingAppWindowTokenRegistry {
+class AnimatingActivityRegistry {
 
-    private ArraySet<AppWindowToken> mAnimatingTokens = new ArraySet<>();
-    private ArrayMap<AppWindowToken, Runnable> mFinishedTokens = new ArrayMap<>();
+    private ArraySet<ActivityRecord> mAnimatingActivities = new ArraySet<>();
+    private ArrayMap<ActivityRecord, Runnable> mFinishedTokens = new ArrayMap<>();
 
     private ArrayList<Runnable> mTmpRunnableList = new ArrayList<>();
 
     private boolean mEndingDeferredFinish;
 
     /**
-     * Notifies that an {@link AppWindowToken} has started animating.
+     * Notifies that an {@link ActivityRecord} has started animating.
      */
-    void notifyStarting(AppWindowToken token) {
-        mAnimatingTokens.add(token);
+    void notifyStarting(ActivityRecord token) {
+        mAnimatingActivities.add(token);
     }
 
     /**
-     * Notifies that an {@link AppWindowToken} has finished animating.
+     * Notifies that an {@link ActivityRecord} has finished animating.
      */
-    void notifyFinished(AppWindowToken token) {
-        mAnimatingTokens.remove(token);
-        mFinishedTokens.remove(token);
+    void notifyFinished(ActivityRecord activity) {
+        mAnimatingActivities.remove(activity);
+        mFinishedTokens.remove(activity);
 
-        // If we were the last token, make sure the end all deferred finishes.
-        if (mAnimatingTokens.isEmpty()) {
+        // If we were the last activity, make sure the end all deferred finishes.
+        if (mAnimatingActivities.isEmpty()) {
             endDeferringFinished();
         }
     }
 
     /**
-     * Called when an {@link AppWindowToken} is about to finish animating.
+     * Called when an {@link ActivityRecord} is about to finish animating.
      *
      * @param endDeferFinishCallback Callback to run when defer finish should be ended.
      * @return {@code true} if finishing the animation should be deferred, {@code false} otherwise.
      */
-    boolean notifyAboutToFinish(AppWindowToken token, Runnable endDeferFinishCallback) {
-        final boolean removed = mAnimatingTokens.remove(token);
+    boolean notifyAboutToFinish(ActivityRecord activity, Runnable endDeferFinishCallback) {
+        final boolean removed = mAnimatingActivities.remove(activity);
         if (!removed) {
             return false;
         }
 
-        if (mAnimatingTokens.isEmpty()) {
+        if (mAnimatingActivities.isEmpty()) {
 
             // If no animations are animating anymore, finish all others.
             endDeferringFinished();
@@ -79,7 +79,7 @@
         } else {
 
             // Otherwise let's put it into the pending list of to be finished animations.
-            mFinishedTokens.put(token, endDeferFinishCallback);
+            mFinishedTokens.put(activity, endDeferFinishCallback);
             return true;
         }
     }
@@ -110,10 +110,10 @@
     }
 
     void dump(PrintWriter pw, String header, String prefix) {
-        if (!mAnimatingTokens.isEmpty() || !mFinishedTokens.isEmpty()) {
+        if (!mAnimatingActivities.isEmpty() || !mFinishedTokens.isEmpty()) {
             pw.print(prefix); pw.println(header);
             prefix = prefix + "  ";
-            pw.print(prefix); pw.print("mAnimatingTokens="); pw.println(mAnimatingTokens);
+            pw.print(prefix); pw.print("mAnimatingActivities="); pw.println(mAnimatingActivities);
             pw.print(prefix); pw.print("mFinishedTokens="); pw.println(mFinishedTokens);
         }
     }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 394b475..c1143c8 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -338,8 +338,8 @@
         updateBooster();
     }
 
-    void setLastAppTransition(int transit, AppWindowToken openingApp, AppWindowToken closingApp,
-            AppWindowToken changingApp) {
+    void setLastAppTransition(int transit, ActivityRecord openingApp, ActivityRecord closingApp,
+            ActivityRecord changingApp) {
         mLastUsedAppTransition = transit;
         mLastOpeningApp = "" + openingApp;
         mLastClosingApp = "" + closingApp;
@@ -430,7 +430,7 @@
      * @return bit-map of WindowManagerPolicy#FINISH_LAYOUT_REDO_* to indicate whether another
      *         layout pass needs to be done
      */
-    int goodToGo(int transit, AppWindowToken topOpeningApp, ArraySet<AppWindowToken> openingApps) {
+    int goodToGo(int transit, ActivityRecord topOpeningApp, ArraySet<ActivityRecord> openingApps) {
         mNextAppTransition = TRANSIT_UNSET;
         mNextAppTransitionFlags = 0;
         setAppTransitionState(APP_STATE_RUNNING);
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 0c07e15..3bda0c2 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -156,20 +156,20 @@
         final ArraySet<Integer> activityTypes = collectActivityTypes(mDisplayContent.mOpeningApps,
                 mDisplayContent.mClosingApps, mDisplayContent.mChangingApps);
         final boolean allowAnimations = mDisplayContent.getDisplayPolicy().allowAppAnimationsLw();
-        final AppWindowToken animLpToken = allowAnimations
+        final ActivityRecord animLpActivity = allowAnimations
                 ? findAnimLayoutParamsToken(transit, activityTypes)
                 : null;
-        final AppWindowToken topOpeningApp = allowAnimations
+        final ActivityRecord topOpeningApp = allowAnimations
                 ? getTopApp(mDisplayContent.mOpeningApps, false /* ignoreHidden */)
                 : null;
-        final AppWindowToken topClosingApp = allowAnimations
+        final ActivityRecord topClosingApp = allowAnimations
                 ? getTopApp(mDisplayContent.mClosingApps, false /* ignoreHidden */)
                 : null;
-        final AppWindowToken topChangingApp = allowAnimations
+        final ActivityRecord topChangingApp = allowAnimations
                 ? getTopApp(mDisplayContent.mChangingApps, false /* ignoreHidden */)
                 : null;
-        final WindowManager.LayoutParams animLp = getAnimLp(animLpToken);
-        overrideWithRemoteAnimationIfSet(animLpToken, transit, activityTypes);
+        final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);
+        overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
 
         final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mOpeningApps)
                 || containsVoiceInteraction(mDisplayContent.mOpeningApps)
@@ -223,14 +223,14 @@
                 layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
     }
 
-    private static WindowManager.LayoutParams getAnimLp(AppWindowToken wtoken) {
-        final WindowState mainWindow = wtoken != null ? wtoken.findMainWindow() : null;
+    private static WindowManager.LayoutParams getAnimLp(ActivityRecord activity) {
+        final WindowState mainWindow = activity != null ? activity.findMainWindow() : null;
         return mainWindow != null ? mainWindow.mAttrs : null;
     }
 
-    RemoteAnimationAdapter getRemoteAnimationOverride(AppWindowToken animLpToken, int transit,
+    RemoteAnimationAdapter getRemoteAnimationOverride(ActivityRecord animLpActivity, int transit,
             ArraySet<Integer> activityTypes) {
-        final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition();
+        final RemoteAnimationDefinition definition = animLpActivity.getRemoteAnimationDefinition();
         if (definition != null) {
             final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
             if (adapter != null) {
@@ -247,19 +247,19 @@
      * Overrides the pending transition with the remote animation defined for the transition in the
      * set of defined remote animations in the app window token.
      */
-    private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit,
+    private void overrideWithRemoteAnimationIfSet(ActivityRecord animLpActivity, int transit,
             ArraySet<Integer> activityTypes) {
         if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
             // The crash transition has higher priority than any involved remote animations.
             return;
         }
-        if (animLpToken == null) {
+        if (animLpActivity == null) {
             return;
         }
         final RemoteAnimationAdapter adapter =
-                getRemoteAnimationOverride(animLpToken, transit, activityTypes);
+                getRemoteAnimationOverride(animLpActivity, transit, activityTypes);
         if (adapter != null) {
-            animLpToken.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(
+            animLpActivity.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(
                     adapter);
         }
     }
@@ -267,12 +267,12 @@
     /**
      * @return The window token that determines the animation theme.
      */
-    private AppWindowToken findAnimLayoutParamsToken(@WindowManager.TransitionType int transit,
+    private ActivityRecord findAnimLayoutParamsToken(@WindowManager.TransitionType int transit,
             ArraySet<Integer> activityTypes) {
-        AppWindowToken result;
-        final ArraySet<AppWindowToken> closingApps = mDisplayContent.mClosingApps;
-        final ArraySet<AppWindowToken> openingApps = mDisplayContent.mOpeningApps;
-        final ArraySet<AppWindowToken> changingApps = mDisplayContent.mChangingApps;
+        ActivityRecord result;
+        final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
+        final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
+        final ArraySet<ActivityRecord> changingApps = mDisplayContent.mChangingApps;
 
         // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
         result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
@@ -294,8 +294,8 @@
      * @return The set of {@link android.app.WindowConfiguration.ActivityType}s contained in the set
      *         of apps in {@code array1}, {@code array2}, and {@code array3}.
      */
-    private static ArraySet<Integer> collectActivityTypes(ArraySet<AppWindowToken> array1,
-            ArraySet<AppWindowToken> array2, ArraySet<AppWindowToken> array3) {
+    private static ArraySet<Integer> collectActivityTypes(ArraySet<ActivityRecord> array1,
+            ArraySet<ActivityRecord> array2, ArraySet<ActivityRecord> array3) {
         final ArraySet<Integer> result = new ArraySet<>();
         for (int i = array1.size() - 1; i >= 0; i--) {
             result.add(array1.valueAt(i).getActivityType());
@@ -309,16 +309,16 @@
         return result;
     }
 
-    private static AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1,
-            ArraySet<AppWindowToken> array2, ArraySet<AppWindowToken> array3,
-            Predicate<AppWindowToken> filter) {
+    private static ActivityRecord lookForHighestTokenWithFilter(ArraySet<ActivityRecord> array1,
+            ArraySet<ActivityRecord> array2, ArraySet<ActivityRecord> array3,
+            Predicate<ActivityRecord> filter) {
         final int array2base = array1.size();
         final int array3base = array2.size() + array2base;
         final int count = array3base + array3.size();
         int bestPrefixOrderIndex = Integer.MIN_VALUE;
-        AppWindowToken bestToken = null;
+        ActivityRecord bestToken = null;
         for (int i = 0; i < count; i++) {
-            final AppWindowToken wtoken = i < array2base
+            final ActivityRecord wtoken = i < array2base
                     ? array1.valueAt(i)
                     : (i < array3base
                             ? array2.valueAt(i - array2base)
@@ -332,7 +332,7 @@
         return bestToken;
     }
 
-    private boolean containsVoiceInteraction(ArraySet<AppWindowToken> apps) {
+    private boolean containsVoiceInteraction(ArraySet<ActivityRecord> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
             if (apps.valueAt(i).mVoiceInteraction) {
                 return true;
@@ -342,10 +342,10 @@
     }
 
     private void handleOpeningApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
-        final ArraySet<AppWindowToken> openingApps = mDisplayContent.mOpeningApps;
+        final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
         final int appsCount = openingApps.size();
         for (int i = 0; i < appsCount; i++) {
-            AppWindowToken wtoken = openingApps.valueAt(i);
+            ActivityRecord wtoken = openingApps.valueAt(i);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", wtoken);
 
             if (!wtoken.commitVisibility(animLp, true, transit, false, voiceInteraction)) {
@@ -376,10 +376,10 @@
     }
 
     private void handleClosingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
-        final ArraySet<AppWindowToken> closingApps = mDisplayContent.mClosingApps;
+        final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
         final int appsCount = closingApps.size();
         for (int i = 0; i < appsCount; i++) {
-            AppWindowToken wtoken = closingApps.valueAt(i);
+            ActivityRecord wtoken = closingApps.valueAt(i);
 
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now closing app %s", wtoken);
             // TODO: Do we need to add to mNoAnimationNotifyOnTransitionFinished like above if not
@@ -404,17 +404,17 @@
     }
 
     private void handleChangingApps(int transit, LayoutParams animLp, boolean voiceInteraction) {
-        final ArraySet<AppWindowToken> apps = mDisplayContent.mChangingApps;
+        final ArraySet<ActivityRecord> apps = mDisplayContent.mChangingApps;
         final int appsCount = apps.size();
         for (int i = 0; i < appsCount; i++) {
-            AppWindowToken wtoken = apps.valueAt(i);
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", wtoken);
-            wtoken.cancelAnimationOnly();
-            wtoken.applyAnimationLocked(null, transit, true, false);
-            wtoken.updateReportedVisibilityLocked();
+            ActivityRecord activity = apps.valueAt(i);
+            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", activity);
+            activity.cancelAnimationOnly();
+            activity.applyAnimationLocked(null, transit, true, false);
+            activity.updateReportedVisibilityLocked();
             mService.openSurfaceTransaction();
             try {
-                wtoken.showAllWindowsLocked();
+                activity.showAllWindowsLocked();
             } finally {
                 mService.closeSurfaceTransaction("handleChangingApps");
             }
@@ -442,7 +442,7 @@
         }
     }
 
-    private boolean transitionGoodToGo(ArraySet<AppWindowToken> apps, SparseIntArray outReasons) {
+    private boolean transitionGoodToGo(ArraySet<ActivityRecord> apps, SparseIntArray outReasons) {
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                 "Checking %d opening apps (frozen=%b timeout=%b)...", apps.size(),
                 mService.mDisplayFrozen, mDisplayContent.mAppTransition.isTimeout());
@@ -465,25 +465,25 @@
                 return false;
             }
             for (int i = 0; i < apps.size(); i++) {
-                AppWindowToken wtoken = apps.valueAt(i);
+                ActivityRecord activity = apps.valueAt(i);
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                                 "Check opening app=%s: allDrawn=%b startingDisplayed=%b "
                                         + "startingMoved=%b isRelaunching()=%b startingWindow=%s",
-                                wtoken, wtoken.allDrawn, wtoken.startingDisplayed,
-                                wtoken.startingMoved, wtoken.isRelaunching(),
-                                wtoken.startingWindow);
+                                activity, activity.allDrawn, activity.startingDisplayed,
+                                activity.startingMoved, activity.isRelaunching(),
+                                activity.startingWindow);
 
 
-                final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching();
-                if (!allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
+                final boolean allDrawn = activity.allDrawn && !activity.isRelaunching();
+                if (!allDrawn && !activity.startingDisplayed && !activity.startingMoved) {
                     return false;
                 }
-                final int windowingMode = wtoken.getWindowingMode();
+                final int windowingMode = activity.getWindowingMode();
                 if (allDrawn) {
                     outReasons.put(windowingMode,  APP_TRANSITION_WINDOWS_DRAWN);
                 } else {
                     outReasons.put(windowingMode,
-                            wtoken.mStartingData instanceof SplashScreenStartingData
+                            activity.mStartingData instanceof SplashScreenStartingData
                                     ? APP_TRANSITION_SPLASH_SCREEN
                                     : APP_TRANSITION_SNAPSHOT);
                 }
@@ -534,11 +534,11 @@
                 (mWallpaperControllerLocked.isWallpaperTargetAnimating() || !showWallpaper)
                         ? null
                         : wallpaperTarget;
-        final ArraySet<AppWindowToken> openingApps = mDisplayContent.mOpeningApps;
-        final ArraySet<AppWindowToken> closingApps = mDisplayContent.mClosingApps;
-        final AppWindowToken topOpeningApp = getTopApp(mDisplayContent.mOpeningApps,
+        final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
+        final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
+        final ActivityRecord topOpeningApp = getTopApp(mDisplayContent.mOpeningApps,
                 false /* ignoreHidden */);
-        final AppWindowToken topClosingApp = getTopApp(mDisplayContent.mClosingApps,
+        final ActivityRecord topClosingApp = getTopApp(mDisplayContent.mClosingApps,
                 true /* ignoreHidden */);
 
         boolean openingCanBeWallpaperTarget = canBeWallpaperTarget(openingApps);
@@ -571,17 +571,17 @@
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                         "New transit: %s", AppTransition.appTransitionToString(transit));
             } else if (oldWallpaper != null && !mDisplayContent.mOpeningApps.isEmpty()
-                    && !openingApps.contains(oldWallpaper.mAppToken)
-                    && closingApps.contains(oldWallpaper.mAppToken)
-                    && topClosingApp == oldWallpaper.mAppToken) {
+                    && !openingApps.contains(oldWallpaper.mActivityRecord)
+                    && closingApps.contains(oldWallpaper.mActivityRecord)
+                    && topClosingApp == oldWallpaper.mActivityRecord) {
                 // We are transitioning from an activity with a wallpaper to one without.
                 transit = TRANSIT_WALLPAPER_CLOSE;
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                         "New transit away from wallpaper: %s",
                                 AppTransition.appTransitionToString(transit));
             } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()
-                    && openingApps.contains(wallpaperTarget.mAppToken)
-                    && topOpeningApp == wallpaperTarget.mAppToken
+                    && openingApps.contains(wallpaperTarget.mActivityRecord)
+                    && topOpeningApp == wallpaperTarget.mActivityRecord
                     && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE) {
                 // We are transitioning from an activity without
                 // a wallpaper to now showing the wallpaper
@@ -616,10 +616,10 @@
         boolean allOpeningVisible = true;
         boolean allTranslucentOpeningApps = !mDisplayContent.mOpeningApps.isEmpty();
         for (int i = mDisplayContent.mOpeningApps.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mDisplayContent.mOpeningApps.valueAt(i);
-            if (!token.isVisible()) {
+            final ActivityRecord activity = mDisplayContent.mOpeningApps.valueAt(i);
+            if (!activity.isVisible()) {
                 allOpeningVisible = false;
-                if (token.fillsParent()) {
+                if (activity.fillsParent()) {
                     allTranslucentOpeningApps = false;
                 }
             }
@@ -660,13 +660,13 @@
             return false;
         }
         // check that all components are in the task.
-        for (AppWindowToken activity : mDisplayContent.mOpeningApps) {
+        for (ActivityRecord activity : mDisplayContent.mOpeningApps) {
             Task activityTask = activity.getTask();
             if (activityTask != task) {
                 return false;
             }
         }
-        for (AppWindowToken activity : mDisplayContent.mClosingApps) {
+        for (ActivityRecord activity : mDisplayContent.mClosingApps) {
             if (activity.getTask() != task) {
                 return false;
             }
@@ -674,7 +674,7 @@
         return true;
     }
 
-    private boolean canBeWallpaperTarget(ArraySet<AppWindowToken> apps) {
+    private boolean canBeWallpaperTarget(ArraySet<ActivityRecord> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
             if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
                 return true;
@@ -684,18 +684,18 @@
     }
 
     /**
-     * Finds the top app in a list of apps, using its {@link AppWindowToken#getPrefixOrderIndex} to
+     * Finds the top app in a list of apps, using its {@link ActivityRecord#getPrefixOrderIndex} to
      * compare z-order.
      *
      * @param apps The list of apps to search.
-     * @param ignoreHidden If set to true, ignores apps that are {@link AppWindowToken#isHidden}.
-     * @return The top {@link AppWindowToken}.
+     * @param ignoreHidden If set to true, ignores apps that are {@link ActivityRecord#isHidden}.
+     * @return The top {@link ActivityRecord}.
      */
-    private AppWindowToken getTopApp(ArraySet<AppWindowToken> apps, boolean ignoreHidden) {
+    private ActivityRecord getTopApp(ArraySet<ActivityRecord> apps, boolean ignoreHidden) {
         int topPrefixOrderIndex = Integer.MIN_VALUE;
-        AppWindowToken topApp = null;
+        ActivityRecord topApp = null;
         for (int i = apps.size() - 1; i >= 0; i--) {
-            final AppWindowToken app = apps.valueAt(i);
+            final ActivityRecord app = apps.valueAt(i);
             if (ignoreHidden && app.isHidden()) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 2b05024..acd96e9 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -44,39 +44,39 @@
 import java.util.function.Supplier;
 
 /**
- * Represents a surface that is displayed over an {@link AppWindowToken}
+ * Represents a surface that is displayed over an {@link ActivityRecord}
  */
 class AppWindowThumbnail implements Animatable {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowThumbnail" : TAG_WM;
 
-    private final AppWindowToken mAppToken;
+    private final ActivityRecord mActivityRecord;
     private SurfaceControl mSurfaceControl;
     private final SurfaceAnimator mSurfaceAnimator;
     private final int mWidth;
     private final int mHeight;
     private final boolean mRelative;
 
-    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
             GraphicBuffer thumbnailHeader) {
-        this(surfaceFactory, t, appToken, thumbnailHeader, false /* relative */);
+        this(surfaceFactory, t, activity, thumbnailHeader, false /* relative */);
     }
 
     /**
      * @param t Transaction to create the thumbnail in.
-     * @param appToken {@link AppWindowToken} to associate this thumbnail with.
+     * @param activity {@link ActivityRecord} to associate this thumbnail with.
      * @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with.
-     * @param relative Whether this thumbnail will be a child of appToken (and thus positioned
+     * @param relative Whether this thumbnail will be a child of activity (and thus positioned
      *                 relative to it) or not.
      */
-    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
             GraphicBuffer thumbnailHeader, boolean relative) {
-        this(t, appToken, thumbnailHeader, relative, surfaceFactory.get(), null);
+        this(t, activity, thumbnailHeader, relative, surfaceFactory.get(), null);
     }
 
-    AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
+    AppWindowThumbnail(Transaction t, ActivityRecord activity, GraphicBuffer thumbnailHeader,
             boolean relative, Surface drawSurface, SurfaceAnimator animator) {
-        mAppToken = appToken;
+        mActivityRecord = activity;
         mRelative = relative;
         if (animator != null) {
             mSurfaceAnimator = animator;
@@ -84,22 +84,22 @@
             // We can't use a delegating constructor since we need to
             // reference this::onAnimationFinished
             mSurfaceAnimator =
-                new SurfaceAnimator(this, this::onAnimationFinished, appToken.mWmService);
+                new SurfaceAnimator(this, this::onAnimationFinished, activity.mWmService);
         }
         mWidth = thumbnailHeader.getWidth();
         mHeight = thumbnailHeader.getHeight();
 
         // Create a new surface for the thumbnail
-        WindowState window = appToken.findMainWindow();
+        WindowState window = mActivityRecord.findMainWindow();
 
         // TODO: This should be attached as a child to the app token, once the thumbnail animations
         // use relative coordinates. Once we start animating task we can also consider attaching
         // this to the task.
-        mSurfaceControl = appToken.makeSurface()
-                .setName("thumbnail anim: " + appToken.toString())
+        mSurfaceControl = mActivityRecord.makeSurface()
+                .setName("thumbnail anim: " + mActivityRecord.toString())
                 .setBufferSize(mWidth, mHeight)
                 .setFormat(PixelFormat.TRANSLUCENT)
-                .setMetadata(METADATA_WINDOW_TYPE, appToken.windowType)
+                .setMetadata(METADATA_WINDOW_TYPE, mActivityRecord.windowType)
                 .setMetadata(METADATA_OWNER_UID,
                         window != null ? window.mOwnerUid : Binder.getCallingUid())
                 .build();
@@ -116,7 +116,7 @@
         // task.
         t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
         if (relative) {
-            t.reparent(mSurfaceControl, appToken.getSurfaceControl());
+            t.reparent(mSurfaceControl, mActivityRecord.getSurfaceControl());
         }
     }
 
@@ -126,12 +126,12 @@
 
     void startAnimation(Transaction t, Animation anim, Point position) {
         anim.restrictDuration(MAX_ANIMATION_DURATION);
-        anim.scaleCurrentDuration(mAppToken.mWmService.getTransitionAnimationScaleLocked());
+        anim.scaleCurrentDuration(mActivityRecord.mWmService.getTransitionAnimationScaleLocked());
         mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
                 new WindowAnimationSpec(anim, position,
-                        mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame(),
-                        mAppToken.getDisplayContent().getWindowCornerRadius()),
-                mAppToken.mWmService.mSurfaceAnimationRunner), false /* hidden */);
+                        mActivityRecord.getDisplayContent().mAppTransition.canSkipFirstFrame(),
+                        mActivityRecord.getDisplayContent().getWindowCornerRadius()),
+                mActivityRecord.mWmService.mSurfaceAnimationRunner), false /* hidden */);
     }
 
     /**
@@ -179,19 +179,19 @@
 
     @Override
     public Transaction getPendingTransaction() {
-        return mAppToken.getPendingTransaction();
+        return mActivityRecord.getPendingTransaction();
     }
 
     @Override
     public void commitPendingTransaction() {
-        mAppToken.commitPendingTransaction();
+        mActivityRecord.commitPendingTransaction();
     }
 
     @Override
     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
         t.setLayer(leash, Integer.MAX_VALUE);
         if (mRelative) {
-            t.reparent(leash, mAppToken.getSurfaceControl());
+            t.reparent(leash, mActivityRecord.getSurfaceControl());
         }
     }
 
@@ -205,7 +205,7 @@
 
     @Override
     public Builder makeAnimationLeash() {
-        return mAppToken.makeSurface();
+        return mActivityRecord.makeSurface();
     }
 
     @Override
@@ -215,12 +215,12 @@
 
     @Override
     public SurfaceControl getAnimationLeashParent() {
-        return mAppToken.getAppAnimationLayer();
+        return mActivityRecord.getAppAnimationLayer();
     }
 
     @Override
     public SurfaceControl getParentSurfaceControl() {
-        return mAppToken.getParentSurfaceControl();
+        return mActivityRecord.getParentSurfaceControl();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
deleted file mode 100644
index e56fdd2..0000000
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ /dev/null
@@ -1,3448 +0,0 @@
-/*
- * Copyright (C) 2011 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.wm;
-
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
-import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
-import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
-import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
-import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.os.Build.VERSION_CODES.HONEYCOMB;
-import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
-import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_UNSET;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
-
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
-import static com.android.server.wm.AppWindowTokenProto.CLIENT_HIDDEN;
-import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
-import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
-import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
-import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
-import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
-import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
-import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
-import static com.android.server.wm.AppWindowTokenProto.NAME;
-import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.REMOVED;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
-import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
-import static com.android.server.wm.IdentifierProto.HASH_CODE;
-import static com.android.server.wm.IdentifierProto.TITLE;
-import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.logWithStack;
-import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
-import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
-
-import android.annotation.CallSuper;
-import android.annotation.Nullable;
-import android.annotation.Size;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.GraphicBuffer;
-import android.graphics.PixelFormat;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.Build;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-import android.view.DisplayInfo;
-import android.view.InputApplicationHandle;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationDefinition;
-import android.view.SurfaceControl;
-import android.view.SurfaceControl.Transaction;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.view.animation.Animation;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ToBooleanFunction;
-import com.android.server.AttributeCache;
-import com.android.server.LocalServices;
-import com.android.server.display.color.ColorDisplayService;
-import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-import com.android.server.protolog.common.ProtoLog;
-import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
-import com.android.server.wm.WindowManagerService.H;
-
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.function.Consumer;
-
-class AppTokenList extends ArrayList<AppWindowToken> {
-}
-
-/**
- * Version of WindowToken that is specifically for a particular application (or
- * really activity) that is displaying windows.
- */
-// TODO: Fully merge this class into ActivityRecord class since they are really the same thing...
-class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
-
-    /**
-     * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
-     */
-    @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
-
-    final ActivityTaskManagerService mAtmService;
-    // Non-null only for application tokens.
-    // TODO: rename to mActivityToken
-    final ActivityRecord.Token appToken;
-    // All about me
-    final ActivityInfo mActivityInfo;
-    // Which user is this running for?
-    final int mUserId;
-    // The package implementing intent's component
-    // TODO: rename to mPackageName
-    final String packageName;
-    // the intent component, or target of an alias.
-    final ComponentName mActivityComponent;
-    boolean mVoiceInteraction;
-
-    /**
-     * The activity is opaque and fills the entire space of this task.
-     * @see WindowContainer#fillsParent()
-     */
-    private boolean mOccludesParent;
-    // Has a wallpaper window as a background.
-    // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
-    // mOccludesParent field.
-    final boolean hasWallpaper;
-    // activity is not displayed?
-    // TODO: rename to mNoDisplay
-    @VisibleForTesting
-    boolean noDisplay;
-    boolean mShowForAllUsers;
-    // TODO: Make this final
-    int mTargetSdk;
-
-    // Flag set while reparenting to prevent actions normally triggered by an individual parent
-    // change.
-    private boolean mReparenting;
-
-    // True if we are current in the process of removing this app token from the display
-    private boolean mRemovingFromDisplay = false;
-
-    // The input dispatching timeout for this application token in nanoseconds.
-    long mInputDispatchingTimeoutNanos;
-
-    // These are used for determining when all windows associated with
-    // an activity have been drawn, so they can be made visible together
-    // at the same time.
-    // initialize so that it doesn't match mTransactionSequence which is an int.
-    private long mLastTransactionSequence = Long.MIN_VALUE;
-    private int mNumInterestingWindows;
-    private int mNumDrawnWindows;
-    boolean inPendingTransaction;
-    boolean allDrawn;
-    private boolean mLastAllDrawn;
-    private boolean mUseTransferredAnimation;
-
-    // Set to true when this app creates a surface while in the middle of an animation. In that
-    // case do not clear allDrawn until the animation completes.
-    boolean deferClearAllDrawn;
-
-    // Is this window's surface needed?  This is almost like hidden, except
-    // it will sometimes be true a little earlier: when the token has
-    // been shown, but is still waiting for its app transition to execute
-    // before making its windows shown.
-    boolean hiddenRequested;
-
-    // Have we told the window clients to hide themselves?
-    private boolean mClientHidden;
-
-    // If true we will defer setting mClientHidden to true and reporting to the client that it is
-    // hidden.
-    boolean mDeferHidingClient;
-
-    // Last visibility state we reported to the app token.
-    boolean reportedVisible;
-
-    // Last drawn state we reported to the app token.
-    private boolean reportedDrawn;
-
-    // Set to true when the token has been removed from the window mgr.
-    boolean removed;
-
-    // Information about an application starting window if displayed.
-    // Note: these are de-referenced before the starting window animates away.
-    StartingData mStartingData;
-    WindowState startingWindow;
-    StartingSurface startingSurface;
-    boolean startingDisplayed;
-    boolean startingMoved;
-
-    // True if the hidden state of this token was forced to false due to a transferred starting
-    // window.
-    private boolean mHiddenSetFromTransferredStartingWindow;
-    boolean firstWindowDrawn;
-    private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
-            new WindowState.UpdateReportedVisibilityResults();
-
-    // Input application handle used by the input dispatcher.
-    final InputApplicationHandle mInputApplicationHandle;
-
-    // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
-    boolean mIsExiting;
-
-    boolean mLaunchTaskBehind;
-    boolean mEnteringAnimation;
-
-    boolean mAppStopped;
-    // A hint to override the window specified rotation animation, or -1 to use the window specified
-    // value. We use this so that we can select the right animation in the cases of starting
-    // windows, where the app hasn't had time to set a value on the window.
-    int mRotationAnimationHint = -1;
-
-    private int mPendingRelaunchCount;
-
-    private boolean mLastContainsShowWhenLockedWindow;
-    private boolean mLastContainsDismissKeyguardWindow;
-
-    ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
-    ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
-
-    /**
-     * The scale to fit at least one side of the activity to its parent. If the activity uses
-     * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
-     */
-    private float mSizeCompatScale = 1f;
-    /**
-     * The bounds in global coordinates for activity in size compatibility mode.
-     * @see ActivityRecord#inSizeCompatMode
-     */
-    private Rect mSizeCompatBounds;
-
-    private boolean mDisablePreviewScreenshots;
-
-    private Task mLastParent;
-
-    /**
-     * @see #currentLaunchCanTurnScreenOn()
-     */
-    private boolean mCurrentLaunchCanTurnScreenOn = true;
-
-    /**
-     * If we are running an animation, this determines the transition type. Must be one of
-     * AppTransition.TRANSIT_* constants.
-     */
-    private int mTransit;
-
-    /**
-     * If we are running an animation, this determines the flags during this animation. Must be a
-     * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
-     */
-    private int mTransitFlags;
-
-    /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
-    private boolean mLastSurfaceShowing = true;
-
-    /**
-     * This gets used during some open/close transitions as well as during a change transition
-     * where it represents the starting-state snapshot.
-     */
-    private AppWindowThumbnail mThumbnail;
-    private final Rect mTransitStartRect = new Rect();
-
-    /**
-     * This leash is used to "freeze" the app surface in place after the state change, but before
-     * the animation is ready to start.
-     */
-    private SurfaceControl mTransitChangeLeash = null;
-
-    /** Have we been asked to have this token keep the screen frozen? */
-    private boolean mFreezingScreen;
-
-    /** Whether this token should be boosted at the top of all app window tokens. */
-    @VisibleForTesting boolean mNeedsZBoost;
-    private Letterbox mLetterbox;
-
-    private final Point mTmpPoint = new Point();
-    private final Rect mTmpRect = new Rect();
-    private final Rect mTmpPrevBounds = new Rect();
-    private RemoteAnimationDefinition mRemoteAnimationDefinition;
-    private AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry;
-
-    /**
-     * A flag to determine if this AWT is in the process of closing or entering PIP. This is needed
-     * to help AWT know that the app is in the process of closing but hasn't yet started closing on
-     * the WM side.
-     */
-    private boolean mWillCloseOrEnterPip;
-
-    /** Layer used to constrain the animation to a token's stack bounds. */
-    SurfaceControl mAnimationBoundsLayer;
-
-    /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
-    boolean mNeedsAnimationBoundsLayer;
-
-    private static final int STARTING_WINDOW_TYPE_NONE = 0;
-    private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
-    private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
-
-    private boolean mShowWhenLocked;
-    private boolean mInheritShownWhenLocked;
-    private boolean mTurnScreenOn;
-
-    private AppSaturationInfo mLastAppSaturationInfo;
-
-    private final ColorDisplayService.ColorTransformController mColorTransformController =
-            (matrix, translation) -> mWmService.mH.post(() -> {
-                synchronized (mWmService.mGlobalLock) {
-                    if (mLastAppSaturationInfo == null) {
-                        mLastAppSaturationInfo = new AppSaturationInfo();
-                    }
-
-                    mLastAppSaturationInfo.setSaturation(matrix, translation);
-                    updateColorTransform();
-                }
-            });
-
-    AppWindowToken(WindowManagerService service, ActivityTaskManagerService atm,
-            ActivityRecord.Token token, ActivityInfo aInfo, ActivityOptions options, Intent intent,
-            DisplayContent dc) {
-        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
-                false /* ownerCanManageAppTokens */);
-        mAtmService = atm;
-        appToken = token;
-        mActivityInfo = aInfo;
-        mUserId = UserHandle.getUserId(mActivityInfo.applicationInfo.uid);
-        packageName = mActivityInfo.applicationInfo.packageName;
-        mInputApplicationHandle = new InputApplicationHandle(appToken);
-
-        // If the class name in the intent doesn't match that of the target, this is probably an
-        // alias. We have to create a new ComponentName object to keep track of the real activity
-        // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
-        if (mActivityInfo.targetActivity == null
-                || (mActivityInfo.targetActivity.equals(intent.getComponent().getClassName())
-                && (mActivityInfo.launchMode == LAUNCH_MULTIPLE
-                || mActivityInfo.launchMode == LAUNCH_SINGLE_TOP))) {
-            mActivityComponent = intent.getComponent();
-        } else {
-            mActivityComponent =
-                    new ComponentName(mActivityInfo.packageName, mActivityInfo.targetActivity);
-        }
-
-        mTargetSdk = mActivityInfo.applicationInfo.targetSdkVersion;
-        mShowForAllUsers = (mActivityInfo.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
-        setOrientation(mActivityInfo.screenOrientation);
-        mRotationAnimationHint = mActivityInfo.rotationAnimation;
-
-        mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
-        mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
-        mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
-
-        int realTheme = mActivityInfo.getThemeResource();
-        if (realTheme == Resources.ID_NULL) {
-            realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
-                    ? android.R.style.Theme : android.R.style.Theme_Holo;
-        }
-
-        final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
-                realTheme, com.android.internal.R.styleable.Window, mUserId);
-
-        if (ent != null) {
-            mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
-            hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
-            noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
-        } else {
-            hasWallpaper = false;
-            noDisplay = false;
-        }
-
-        if (options != null) {
-            mLaunchTaskBehind = options.getLaunchTaskBehind();
-
-            final int rotationAnimation = options.getRotationAnimationHint();
-            // Only override manifest supplied option if set.
-            if (rotationAnimation >= 0) {
-                mRotationAnimationHint = rotationAnimation;
-            }
-        }
-
-        // Application tokens start out hidden.
-        setHidden(true);
-        hiddenRequested = true;
-
-        ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
-                ColorDisplayService.ColorDisplayServiceInternal.class);
-        cds.attachColorTransformController(packageName, mUserId,
-                new WeakReference<>(mColorTransformController));
-    }
-
-    void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
-            long inputDispatchingTimeoutNanos) {
-        mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
-        mVoiceInteraction = voiceInteraction;
-        onDisplayChanged(dc);
-
-        // Application tokens start out hidden.
-        setHidden(true);
-        hiddenRequested = true;
-    }
-
-    void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
-        firstWindowDrawn = true;
-
-        // We now have a good window to show, remove dead placeholders
-        removeDeadWindows();
-
-        if (startingWindow != null) {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
-                        + ": first real window is shown, no animation", win.mToken);
-            // If this initial window is animating, stop it -- we will do an animation to reveal
-            // it from behind the starting window, so there is no need for it to also be doing its
-            // own stuff.
-            win.cancelAnimation();
-        }
-        removeStartingWindow();
-        updateReportedVisibilityLocked();
-    }
-
-    void updateReportedVisibilityLocked() {
-        if (appToken == null) {
-            return;
-        }
-
-        if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
-        final int count = mChildren.size();
-
-        mReportedVisibilityResults.reset();
-
-        for (int i = 0; i < count; i++) {
-            final WindowState win = mChildren.get(i);
-            win.updateReportedVisibility(mReportedVisibilityResults);
-        }
-
-        int numInteresting = mReportedVisibilityResults.numInteresting;
-        int numVisible = mReportedVisibilityResults.numVisible;
-        int numDrawn = mReportedVisibilityResults.numDrawn;
-        boolean nowGone = mReportedVisibilityResults.nowGone;
-
-        boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
-        boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && !isHidden();
-        if (!nowGone) {
-            // If the app is not yet gone, then it can only become visible/drawn.
-            if (!nowDrawn) {
-                nowDrawn = reportedDrawn;
-            }
-            if (!nowVisible) {
-                nowVisible = reportedVisible;
-            }
-        }
-        if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
-                + numInteresting + " visible=" + numVisible);
-        if (nowDrawn != reportedDrawn) {
-            onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
-            reportedDrawn = nowDrawn;
-        }
-        if (nowVisible != reportedVisible) {
-            if (DEBUG_VISIBILITY) Slog.v(TAG,
-                    "Visibility changed in " + this + ": vis=" + nowVisible);
-            reportedVisible = nowVisible;
-            if (nowVisible) {
-                onWindowsVisible();
-            } else {
-                onWindowsGone();
-            }
-        }
-    }
-
-    // Mostly implemented in ActivityRecord.
-    void onWindowsDrawn(boolean drawn, long timestamp) {
-    }
-
-    // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
-    void onWindowsGone() {
-        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
-    }
-
-    // Mostly implemented in ActivityRecord. Keeping here for the logpoint.
-    void onWindowsVisible() {
-        if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
-    }
-
-    boolean isClientHidden() {
-        return mClientHidden;
-    }
-
-    void setClientHidden(boolean hideClient) {
-        if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
-            return;
-        }
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                "setClientHidden: %s clientHidden=%b Callers=%s", this, hideClient,
-                        Debug.getCallers(5));
-        mClientHidden = hideClient;
-        sendAppVisibilityToClients();
-    }
-
-    void setVisibility(boolean visible, boolean deferHidingClient) {
-        final AppTransition appTransition = getDisplayContent().mAppTransition;
-
-        // Don't set visibility to false if we were already not visible. This prevents WM from
-        // adding the app to the closing app list which doesn't make sense for something that is
-        // already not visible. However, set visibility to true even if we are already visible.
-        // This makes sure the app is added to the opening apps list so that the right
-        // transition can be selected.
-        // TODO: Probably a good idea to separate the concept of opening/closing apps from the
-        // concept of setting visibility...
-        if (!visible && hiddenRequested) {
-
-            if (!deferHidingClient && mDeferHidingClient) {
-                // We previously deferred telling the client to hide itself when visibility was
-                // initially set to false. Now we would like it to hide, so go ahead and set it.
-                mDeferHidingClient = deferHidingClient;
-                setClientHidden(true);
-            }
-            return;
-        }
-
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                    "setAppVisibility(%s, visible=%b): %s hidden=%b hiddenRequested=%b Callers=%s",
-                    appToken, visible, appTransition, isHidden(), hiddenRequested,
-                    Debug.getCallers(6));
-
-        final DisplayContent displayContent = getDisplayContent();
-        displayContent.mOpeningApps.remove(this);
-        displayContent.mClosingApps.remove(this);
-        if (isInChangeTransition()) {
-            clearChangeLeash(getPendingTransaction(), true /* cancel */);
-        }
-        displayContent.mChangingApps.remove(this);
-        waitingToShow = false;
-        hiddenRequested = !visible;
-        mDeferHidingClient = deferHidingClient;
-
-        if (!visible) {
-            // If the app is dead while it was visible, we kept its dead window on screen.
-            // Now that the app is going invisible, we can remove it. It will be restarted
-            // if made visible again.
-            removeDeadWindows();
-        } else {
-            if (!appTransition.isTransitionSet()
-                    && appTransition.isReady()) {
-                // Add the app mOpeningApps if transition is unset but ready. This means
-                // we're doing a screen freeze, and the unfreeze will wait for all opening
-                // apps to be ready.
-                displayContent.mOpeningApps.add(this);
-            }
-            startingMoved = false;
-            // If the token is currently hidden (should be the common case), or has been
-            // stopped, then we need to set up to wait for its windows to be ready.
-            if (isHidden() || mAppStopped) {
-                clearAllDrawn();
-
-                // If the app was already visible, don't reset the waitingToShow state.
-                if (isHidden()) {
-                    waitingToShow = true;
-
-                    // If the client isn't hidden, we don't need to reset the drawing state.
-                    if (isClientHidden()) {
-                        // Let's reset the draw state in order to prevent the starting window to be
-                        // immediately dismissed when the app still has the surface.
-                        forAllWindows(w -> {
-                            if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
-                                w.mWinAnimator.resetDrawState();
-
-                                // Force add to mResizingWindows, so that we are guaranteed to get
-                                // another reportDrawn callback.
-                                w.resetLastContentInsets();
-                            }
-                        }, true /* traverseTopToBottom */);
-                    }
-                }
-            }
-
-            // In the case where we are making an app visible but holding off for a transition,
-            // we still need to tell the client to make its windows visible so they get drawn.
-            // Otherwise, we will wait on performing the transition until all windows have been
-            // drawn, they never will be, and we are sad.
-            setClientHidden(false);
-
-            requestUpdateWallpaperIfNeeded();
-
-            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
-            mAppStopped = false;
-
-            transferStartingWindowFromHiddenAboveTokenIfNeeded();
-        }
-
-        // If we are preparing an app transition, then delay changing
-        // the visibility of this token until we execute that transition.
-        if (okToAnimate() && appTransition.isTransitionSet()) {
-            inPendingTransaction = true;
-            if (visible) {
-                displayContent.mOpeningApps.add(this);
-                mEnteringAnimation = true;
-            } else {
-                displayContent.mClosingApps.add(this);
-                mEnteringAnimation = false;
-            }
-            if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
-                // We're launchingBehind, add the launching activity to mOpeningApps.
-                final WindowState win = getDisplayContent().findFocusedWindow();
-                if (win != null) {
-                    final AppWindowToken focusedToken = win.mAppToken;
-                    if (focusedToken != null) {
-                        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
-                                    "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
-                                    focusedToken);
-
-                        // Force animation to be loaded.
-                        displayContent.mOpeningApps.add(focusedToken);
-                    }
-                }
-            }
-            return;
-        }
-
-        commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
-        updateReportedVisibilityLocked();
-    }
-
-    boolean commitVisibility(WindowManager.LayoutParams lp,
-            boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
-
-        boolean delayed = false;
-        inPendingTransaction = false;
-        // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
-        // been set by the app now.
-        mHiddenSetFromTransferredStartingWindow = false;
-
-        // Allow for state changes and animation to be applied if:
-        // * token is transitioning visibility state
-        // * or the token was marked as hidden and is exiting before we had a chance to play the
-        // transition animation
-        // * or this is an opening app and windows are being replaced
-        // * or the token is the opening app and visible while opening task behind existing one.
-        final DisplayContent displayContent = getDisplayContent();
-        boolean visibilityChanged = false;
-        if (isHidden() == visible || (isHidden() && mIsExiting)
-                || (visible && waitingForReplacement())
-                || (visible && displayContent.mOpeningApps.contains(this)
-                && displayContent.mAppTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND)) {
-            final AccessibilityController accessibilityController =
-                    mWmService.mAccessibilityController;
-            boolean changed = false;
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                    "Changing app %s hidden=%b performLayout=%b", this, isHidden(),
-                            performLayout);
-
-            boolean runningAppAnimation = false;
-
-            if (transit != WindowManager.TRANSIT_UNSET) {
-                if (mUseTransferredAnimation) {
-                    runningAppAnimation = isReallyAnimating();
-                } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
-                    runningAppAnimation = true;
-                }
-                delayed = runningAppAnimation;
-                final WindowState window = findMainWindow();
-                if (window != null && accessibilityController != null) {
-                    accessibilityController.onAppWindowTransitionLocked(window, transit);
-                }
-                changed = true;
-            }
-
-            final int windowsCount = mChildren.size();
-            for (int i = 0; i < windowsCount; i++) {
-                final WindowState win = mChildren.get(i);
-                changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
-            }
-
-            setHidden(!visible);
-            hiddenRequested = !visible;
-            visibilityChanged = true;
-            if (!visible) {
-                stopFreezingScreen(true, true);
-            } else {
-                // If we are being set visible, and the starting window is not yet displayed,
-                // then make sure it doesn't get displayed.
-                if (startingWindow != null && !startingWindow.isDrawnLw()) {
-                    startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
-                    startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
-                }
-
-                // We are becoming visible, so better freeze the screen with the windows that are
-                // getting visible so we also wait for them.
-                forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
-            }
-
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                        "commitVisibility: %s: hidden=%b hiddenRequested=%b", this,
-                                isHidden(), hiddenRequested);
-
-            if (changed) {
-                displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
-                if (performLayout) {
-                    mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                            false /*updateInputWindows*/);
-                    mWmService.mWindowPlacerLocked.performSurfacePlacement();
-                }
-                displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
-            }
-        }
-        mUseTransferredAnimation = false;
-
-        if (isReallyAnimating()) {
-            delayed = true;
-        } else {
-
-            // We aren't animating anything, but exiting windows rely on the animation finished
-            // callback being called in case the AppWindowToken was pretending to be animating,
-            // which we might have done because we were in closing/opening apps list.
-            onAnimationFinished();
-        }
-
-        for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
-            if ((mChildren.get(i)).isSelfOrChildAnimating()) {
-                delayed = true;
-            }
-        }
-
-        if (visibilityChanged) {
-            if (visible && !delayed) {
-                // The token was made immediately visible, there will be no entrance animation.
-                // We need to inform the client the enter animation was finished.
-                mEnteringAnimation = true;
-                mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
-                        token);
-            }
-
-            // If we're becoming visible, immediately change client visibility as well. there seem
-            // to be some edge cases where we change our visibility but client visibility never gets
-            // updated.
-            // If we're becoming invisible, update the client visibility if we are not running an
-            // animation. Otherwise, we'll update client visibility in onAnimationFinished.
-            if (visible || !isReallyAnimating()) {
-                setClientHidden(!visible);
-            }
-
-            if (!displayContent.mClosingApps.contains(this)
-                    && !displayContent.mOpeningApps.contains(this)) {
-                // The token is not closing nor opening, so even if there is an animation set, that
-                // doesn't mean that it goes through the normal app transition cycle so we have
-                // to inform the docked controller about visibility change.
-                // TODO(multi-display): notify docked divider on all displays where visibility was
-                // affected.
-                displayContent.getDockedDividerController().notifyAppVisibilityChanged();
-
-                // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
-                // will not be taken.
-                mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
-            }
-
-            // If we are hidden but there is no delay needed we immediately
-            // apply the Surface transaction so that the ActivityManager
-            // can have some guarantee on the Surface state following
-            // setting the visibility. This captures cases like dismissing
-            // the docked or pinned stack where there is no app transition.
-            //
-            // In the case of a "Null" animation, there will be
-            // no animation but there will still be a transition set.
-            // We still need to delay hiding the surface such that it
-            // can be synchronized with showing the next surface in the transition.
-            if (isHidden() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
-                SurfaceControl.openTransaction();
-                for (int i = mChildren.size() - 1; i >= 0; i--) {
-                    mChildren.get(i).mWinAnimator.hide("immediately hidden");
-                }
-                SurfaceControl.closeTransaction();
-            }
-        }
-
-        return delayed;
-    }
-
-    boolean mayFreezeScreenLocked() {
-        return false;
-    }
-
-    void reportDescendantOrientationChangeIfNeeded() {
-        // Orientation request is exposed only when we're visible. Therefore visibility change
-        // will change requested orientation. Notify upward the hierarchy ladder to adjust
-        // configuration. This is important to cases where activities with incompatible
-        // orientations launch, or user goes back from an activity of bi-orientation to an
-        // activity with specified orientation.
-        if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
-            return;
-        }
-
-        final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
-        onDescendantOrientationChanged(freezeToken, this);
-    }
-
-    /**
-     * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
-     *         true.
-     */
-    WindowState getTopFullscreenWindow() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            if (win != null && win.mAttrs.isFullscreen()) {
-                return win;
-            }
-        }
-        return null;
-    }
-
-    WindowState findMainWindow() {
-        return findMainWindow(true);
-    }
-
-    /**
-     * Finds the main window that either has type base application or application starting if
-     * requested.
-     *
-     * @param includeStartingApp Allow to search application-starting windows to also be returned.
-     * @return The main window of type base application or application starting if requested.
-     */
-    WindowState findMainWindow(boolean includeStartingApp) {
-        WindowState candidate = null;
-        for (int j = mChildren.size() - 1; j >= 0; --j) {
-            final WindowState win = mChildren.get(j);
-            final int type = win.mAttrs.type;
-            // No need to loop through child window as base application and starting types can't be
-            // child windows.
-            if (type == TYPE_BASE_APPLICATION
-                    || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
-                // In cases where there are multiple windows, we prefer the non-exiting window. This
-                // happens for example when replacing windows during an activity relaunch. When
-                // constructing the animation, we want the new window, not the exiting one.
-                if (win.mAnimatingExit) {
-                    candidate = win;
-                } else {
-                    return win;
-                }
-            }
-        }
-        return candidate;
-    }
-
-    boolean isAlwaysFocusable() {
-        return (mActivityInfo.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
-    }
-
-    // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
-    // focusable means resumeable. I guess with that in mind maybe we should rename the other
-    // method to isResumeable() or something like that.
-    boolean windowsAreFocusable() {
-        if (mTargetSdk < Build.VERSION_CODES.Q) {
-            final int pid = getPid();
-            final AppWindowToken topFocusedAppOfMyProcess =
-                    mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
-            if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
-                // For the apps below Q, there can be only one app which has the focused window per
-                // process, because legacy apps may not be ready for a multi-focus system.
-                return false;
-            }
-        }
-        return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable();
-    }
-
-    // Mostly implemented in ActivityRecord...
-    int getPid() {
-        return 0;
-    }
-
-    @Override
-    boolean isVisible() {
-        // If the app token isn't hidden then it is considered visible and there is no need to check
-        // its children windows to see if they are visible.
-        return !isHidden();
-    }
-
-    @Override
-    void removeImmediately() {
-        onRemovedFromDisplay();
-        super.removeImmediately();
-    }
-
-    @Override
-    void removeIfPossible() {
-        mIsExiting = false;
-        removeAllWindowsIfPossible();
-        removeImmediately();
-    }
-
-    @Override
-    boolean checkCompleteDeferredRemoval() {
-        if (mIsExiting) {
-            removeIfPossible();
-        }
-        return super.checkCompleteDeferredRemoval();
-    }
-
-    void onRemovedFromDisplay() {
-        if (mRemovingFromDisplay) {
-            return;
-        }
-        mRemovingFromDisplay = true;
-
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
-
-        boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
-
-        getDisplayContent().mOpeningApps.remove(this);
-        getDisplayContent().mChangingApps.remove(this);
-        getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
-        mWmService.mTaskSnapshotController.onAppRemoved(this);
-        waitingToShow = false;
-        if (getDisplayContent().mClosingApps.contains(this)) {
-            delayed = true;
-        } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
-            getDisplayContent().mClosingApps.add(this);
-            delayed = true;
-        }
-
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
-                        getAnimation(), isSelfAnimating());
-
-        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
-                + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
-
-        if (mStartingData != null) {
-            removeStartingWindow();
-        }
-
-        // If this window was animating, then we need to ensure that the app transition notifies
-        // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
-        // so add to that list now
-        if (isSelfAnimating()) {
-            getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
-        }
-
-        final TaskStack stack = getStack();
-        if (delayed && !isEmpty()) {
-            // set the token aside because it has an active animation to be finished
-            ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                    "removeAppToken make exiting: %s", this);
-            if (stack != null) {
-                stack.mExitingAppTokens.add(this);
-            }
-            mIsExiting = true;
-        } else {
-            // Make sure there is no animation running on this token, so any windows associated
-            // with it will be removed as soon as their animations are complete
-            cancelAnimation();
-            if (stack != null) {
-                stack.mExitingAppTokens.remove(this);
-            }
-            removeIfPossible();
-        }
-
-        removed = true;
-        stopFreezingScreen(true, true);
-
-        final DisplayContent dc = getDisplayContent();
-        if (dc.mFocusedApp == this) {
-            ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
-                    "Removing focused app token:%s displayId=%d", this,
-                            dc.getDisplayId());
-            dc.setFocusedApp(null);
-            mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
-        }
-        if (mLetterbox != null) {
-            mLetterbox.destroy();
-            mLetterbox = null;
-        }
-
-        if (!delayed) {
-            updateReportedVisibilityLocked();
-        }
-
-        // Reset the last saved PiP snap fraction on removal.
-        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
-
-        mRemovingFromDisplay = false;
-    }
-
-    void clearAnimatingFlags() {
-        boolean wallpaperMightChange = false;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            wallpaperMightChange |= win.clearAnimatingFlags();
-        }
-        if (wallpaperMightChange) {
-            requestUpdateWallpaperIfNeeded();
-        }
-    }
-
-    void destroySurfaces() {
-        destroySurfaces(false /*cleanupOnResume*/);
-    }
-
-    /**
-     * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
-     * the client has finished with them.
-     *
-     * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
-     * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
-     * others so that they are ready to be reused. If set to false (common case), destroy all
-     * surfaces that's eligible, if the app is already stopped.
-     */
-    private void destroySurfaces(boolean cleanupOnResume) {
-        boolean destroyedSomething = false;
-
-        // Copying to a different list as multiple children can be removed.
-        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
-        for (int i = children.size() - 1; i >= 0; i--) {
-            final WindowState win = children.get(i);
-            destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
-        }
-        if (destroyedSomething) {
-            final DisplayContent dc = getDisplayContent();
-            dc.assignWindowLayers(true /*setLayoutNeeded*/);
-            updateLetterboxSurface(null);
-        }
-    }
-
-    /**
-     * Notify that the app is now resumed, and it was not stopped before, perform a clean
-     * up of the surfaces
-     */
-    void notifyAppResumed(boolean wasStopped) {
-        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
-                wasStopped, this);
-        mAppStopped = false;
-        // Allow the window to turn the screen on once the app is resumed again.
-        setCurrentLaunchCanTurnScreenOn(true);
-        if (!wasStopped) {
-            destroySurfaces(true /*cleanupOnResume*/);
-        }
-    }
-
-    /**
-     * Notify that the app has stopped, and it is okay to destroy any surfaces which were
-     * keeping alive in case they were still being used.
-     */
-    void notifyAppStopped() {
-        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
-        mAppStopped = true;
-        // Reset the last saved PiP snap fraction on app stop.
-        mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent);
-        destroySurfaces();
-        // Remove any starting window that was added for this app if they are still around.
-        removeStartingWindow();
-    }
-
-    void clearAllDrawn() {
-        allDrawn = false;
-        deferClearAllDrawn = false;
-    }
-
-    Task getTask() {
-        return (Task) getParent();
-    }
-
-    TaskStack getStack() {
-        final Task task = getTask();
-        if (task != null) {
-            return task.mStack;
-        } else {
-            return null;
-        }
-    }
-
-    @Override
-    void onParentChanged() {
-        super.onParentChanged();
-
-        final Task task = getTask();
-
-        // When the associated task is {@code null}, the {@link AppWindowToken} can no longer
-        // access visual elements like the {@link DisplayContent}. We must remove any associations
-        // such as animations.
-        if (!mReparenting) {
-            if (task == null) {
-                // It is possible we have been marked as a closing app earlier. We must remove ourselves
-                // from this list so we do not participate in any future animations.
-                if (getDisplayContent() != null) {
-                    getDisplayContent().mClosingApps.remove(this);
-                }
-            } else if (mLastParent != null && mLastParent.mStack != null) {
-                task.mStack.mExitingAppTokens.remove(this);
-            }
-        }
-        final TaskStack stack = getStack();
-
-        // If we reparent, make sure to remove ourselves from the old animation registry.
-        if (mAnimatingAppWindowTokenRegistry != null) {
-            mAnimatingAppWindowTokenRegistry.notifyFinished(this);
-        }
-        mAnimatingAppWindowTokenRegistry = stack != null
-                ? stack.getAnimatingAppWindowTokenRegistry()
-                : null;
-
-        mLastParent = task;
-
-        updateColorTransform();
-    }
-
-    void postWindowRemoveStartingWindowCleanup(WindowState win) {
-        // TODO: Something smells about the code below...Is there a better way?
-        if (startingWindow == win) {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
-            removeStartingWindow();
-        } else if (mChildren.size() == 0) {
-            // If this is the last window and we had requested a starting transition window,
-            // well there is no point now.
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
-            mStartingData = null;
-            if (mHiddenSetFromTransferredStartingWindow) {
-                // We set the hidden state to false for the token from a transferred starting window.
-                // We now reset it back to true since the starting window was the last window in the
-                // token.
-                setHidden(true);
-            }
-        } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
-            // If this is the last window except for a starting transition window,
-            // we need to get rid of the starting transition.
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
-            removeStartingWindow();
-        }
-    }
-
-    void removeDeadWindows() {
-        for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
-            WindowState win = mChildren.get(winNdx);
-            if (win.mAppDied) {
-                ProtoLog.w(WM_DEBUG_ADD_REMOVE,
-                        "removeDeadWindows: %s", win);
-                // Set mDestroying, we don't want any animation or delayed removal here.
-                win.mDestroying = true;
-                // Also removes child windows.
-                win.removeIfPossible();
-            }
-        }
-    }
-
-    boolean hasWindowsAlive() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            // No need to loop through child windows as the answer should be the same as that of the
-            // parent window.
-            if (!(mChildren.get(i)).mAppDied) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    void setWillReplaceWindows(boolean animate) {
-        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
-                "Marking app token %s with replacing windows.", this);
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.setWillReplaceWindow(animate);
-        }
-    }
-
-    void setWillReplaceChildWindows() {
-        ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
-                + " with replacing child windows.", this);
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.setWillReplaceChildWindows();
-        }
-    }
-
-    void clearWillReplaceWindows() {
-        ProtoLog.d(WM_DEBUG_ADD_REMOVE,
-                "Resetting app token %s of replacing window marks.", this);
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.clearWillReplaceWindow();
-        }
-    }
-
-    void requestUpdateWallpaperIfNeeded() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.requestUpdateWallpaperIfNeeded();
-        }
-    }
-
-    boolean isRelaunching() {
-        return mPendingRelaunchCount > 0;
-    }
-
-    boolean shouldFreezeBounds() {
-        final Task task = getTask();
-
-        // For freeform windows, we can't freeze the bounds at the moment because this would make
-        // the resizing unresponsive.
-        if (task == null || task.inFreeformWindowingMode()) {
-            return false;
-        }
-
-        // We freeze the bounds while drag resizing to deal with the time between
-        // the divider/drag handle being released, and the handling it's new
-        // configuration. If we are relaunched outside of the drag resizing state,
-        // we need to be careful not to do this.
-        return getTask().isDragResizing();
-    }
-
-    void startRelaunching() {
-        if (shouldFreezeBounds()) {
-            freezeBounds();
-        }
-
-        // In the process of tearing down before relaunching, the app will
-        // try and clean up it's child surfaces. We need to prevent this from
-        // happening, so we sever the children, transfering their ownership
-        // from the client it-self to the parent surface (owned by us).
-        detachChildren();
-
-        mPendingRelaunchCount++;
-    }
-
-    void detachChildren() {
-        SurfaceControl.openTransaction();
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            w.mWinAnimator.detachChildren();
-        }
-        SurfaceControl.closeTransaction();
-    }
-
-    void finishRelaunching() {
-        unfreezeBounds();
-
-        if (mPendingRelaunchCount > 0) {
-            mPendingRelaunchCount--;
-        } else {
-            // Update keyguard flags upon finishing relaunch.
-            checkKeyguardFlagsChanged();
-        }
-    }
-
-    void clearRelaunching() {
-        if (mPendingRelaunchCount == 0) {
-            return;
-        }
-        unfreezeBounds();
-        mPendingRelaunchCount = 0;
-    }
-
-    /**
-     * Returns true if the new child window we are adding to this token is considered greater than
-     * the existing child window in this token in terms of z-order.
-     */
-    @Override
-    protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
-            WindowState existingWindow) {
-        final int type1 = newWindow.mAttrs.type;
-        final int type2 = existingWindow.mAttrs.type;
-
-        // Base application windows should be z-ordered BELOW all other windows in the app token.
-        if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
-            return false;
-        } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
-            return true;
-        }
-
-        // Starting windows should be z-ordered ABOVE all other windows in the app token.
-        if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
-            return true;
-        } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
-            return false;
-        }
-
-        // Otherwise the new window is greater than the existing window.
-        return true;
-    }
-
-    /**
-     * @return {@code true} if starting window is in app's hierarchy.
-     */
-    boolean hasStartingWindow() {
-        if (startingDisplayed || mStartingData != null) {
-            return true;
-        }
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    void addWindow(WindowState w) {
-        super.addWindow(w);
-
-        boolean gotReplacementWindow = false;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState candidate = mChildren.get(i);
-            gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
-        }
-
-        // if we got a replacement window, reset the timeout to give drawing more time
-        if (gotReplacementWindow) {
-            mWmService.scheduleWindowReplacementTimeouts(this);
-        }
-        checkKeyguardFlagsChanged();
-    }
-
-    @Override
-    void removeChild(WindowState child) {
-        if (!mChildren.contains(child)) {
-            // This can be true when testing.
-            return;
-        }
-        super.removeChild(child);
-        checkKeyguardFlagsChanged();
-        updateLetterboxSurface(child);
-    }
-
-    private boolean waitingForReplacement() {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState candidate = mChildren.get(i);
-            if (candidate.waitingForReplacement()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    void onWindowReplacementTimeout() {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            (mChildren.get(i)).onWindowReplacementTimeout();
-        }
-    }
-
-    void reparent(Task task, int position) {
-        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving app token=%s"
-                    + " to task=%d at %d", this, task.mTaskId, position);
-
-        if (task == null) {
-            throw new IllegalArgumentException("reparent: could not find task");
-        }
-        final Task currentTask = getTask();
-        if (task == currentTask) {
-            throw new IllegalArgumentException(
-                    "window token=" + this + " already child of task=" + currentTask);
-        }
-
-        if (currentTask.mStack != task.mStack) {
-            throw new IllegalArgumentException(
-                    "window token=" + this + " current task=" + currentTask
-                        + " belongs to a different stack than " + task);
-        }
-
-        ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reParentWindowToken: removing window token=%s"
-                + " from task=%s"  , this, currentTask);
-        final DisplayContent prevDisplayContent = getDisplayContent();
-
-        mReparenting = true;
-
-        getParent().removeChild(this);
-        task.addChild((ActivityRecord) this, position);
-
-        mReparenting = false;
-
-        // Relayout display(s).
-        final DisplayContent displayContent = task.getDisplayContent();
-        displayContent.setLayoutNeeded();
-        if (prevDisplayContent != displayContent) {
-            onDisplayChanged(displayContent);
-            prevDisplayContent.setLayoutNeeded();
-        }
-        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-    }
-
-    @Override
-    void onDisplayChanged(DisplayContent dc) {
-        DisplayContent prevDc = mDisplayContent;
-        super.onDisplayChanged(dc);
-        if (prevDc == null || prevDc == mDisplayContent) {
-            return;
-        }
-
-        if (prevDc.mOpeningApps.remove(this)) {
-            // Transfer opening transition to new display.
-            mDisplayContent.mOpeningApps.add(this);
-            mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
-            mDisplayContent.executeAppTransition();
-        }
-
-        if (prevDc.mChangingApps.remove(this)) {
-            // This gets called *after* the AppWindowToken has been reparented to the new display.
-            // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
-            // so this token is now "frozen" while waiting for the animation to start on prevDc
-            // (which will be cancelled since the window is no-longer a child). However, since this
-            // is no longer a child of prevDc, this won't be notified of the cancelled animation,
-            // so we need to cancel the change transition here.
-            clearChangeLeash(getPendingTransaction(), true /* cancel */);
-        }
-        prevDc.mClosingApps.remove(this);
-
-        if (prevDc.mFocusedApp == this) {
-            prevDc.setFocusedApp(null);
-            final TaskStack stack = dc.getTopStack();
-            if (stack != null) {
-                final Task task = stack.getTopChild();
-                if (task != null && task.getTopChild() == this) {
-                    dc.setFocusedApp(this);
-                }
-            }
-        }
-
-        if (mLetterbox != null) {
-            mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
-        }
-    }
-
-    /**
-     * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
-     * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
-     * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
-     * with a queue.
-     */
-    private void freezeBounds() {
-        final Task task = getTask();
-        mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
-
-        if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
-            // We didn't call prepareFreezingBounds on the task, so use the current value.
-            mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
-        } else {
-            mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
-        }
-        // Calling unset() to make it equal to Configuration.EMPTY.
-        task.mPreparedFrozenMergedConfig.unset();
-    }
-
-    /**
-     * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
-     */
-    private void unfreezeBounds() {
-        if (mFrozenBounds.isEmpty()) {
-            return;
-        }
-        mFrozenBounds.remove();
-        if (!mFrozenMergedConfig.isEmpty()) {
-            mFrozenMergedConfig.remove();
-        }
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            win.onUnfreezeBounds();
-        }
-        mWmService.mWindowPlacerLocked.performSurfacePlacement();
-    }
-
-    void setAppLayoutChanges(int changes, String reason) {
-        if (!mChildren.isEmpty()) {
-            final DisplayContent dc = getDisplayContent();
-            dc.pendingLayoutChanges |= changes;
-            if (DEBUG_LAYOUT_REPEATS) {
-                mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
-            }
-        }
-    }
-
-    void removeReplacedWindowIfNeeded(WindowState replacement) {
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final WindowState win = mChildren.get(i);
-            if (win.removeReplacedWindowIfNeeded(replacement)) {
-                return;
-            }
-        }
-    }
-
-    void startFreezingScreen() {
-        ProtoLog.i(WM_DEBUG_ORIENTATION,
-                "Set freezing of %s: hidden=%b freezing=%b hiddenRequested=%b. %s",
-                        appToken, isHidden(), mFreezingScreen, hiddenRequested,
-                new RuntimeException().fillInStackTrace());
-        if (!hiddenRequested) {
-            if (!mFreezingScreen) {
-                mFreezingScreen = true;
-                mWmService.registerAppFreezeListener(this);
-                mWmService.mAppsFreezingScreen++;
-                if (mWmService.mAppsFreezingScreen == 1) {
-                    mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
-                    mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
-                    mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
-                }
-            }
-            final int count = mChildren.size();
-            for (int i = 0; i < count; i++) {
-                final WindowState w = mChildren.get(i);
-                w.onStartFreezingScreen();
-            }
-        }
-    }
-
-    void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
-        if (!mFreezingScreen) {
-            return;
-        }
-        ProtoLog.v(WM_DEBUG_ORIENTATION,
-                "Clear freezing of %s force=%b", this, force);
-        final int count = mChildren.size();
-        boolean unfrozeWindows = false;
-        for (int i = 0; i < count; i++) {
-            final WindowState w = mChildren.get(i);
-            unfrozeWindows |= w.onStopFreezingScreen();
-        }
-        if (force || unfrozeWindows) {
-            ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
-            mFreezingScreen = false;
-            mWmService.unregisterAppFreezeListener(this);
-            mWmService.mAppsFreezingScreen--;
-            mWmService.mLastFinishedFreezeSource = this;
-        }
-        if (unfreezeSurfaceNow) {
-            if (unfrozeWindows) {
-                mWmService.mWindowPlacerLocked.performSurfacePlacement();
-            }
-            mWmService.stopFreezingDisplayLocked();
-        }
-    }
-
-    @Override
-    public void onAppFreezeTimeout() {
-        Slog.w(TAG_WM, "Force clearing freeze: " + this);
-        stopFreezingScreen(true, true);
-    }
-
-    /**
-     * Tries to transfer the starting window from a token that's above ourselves in the task but
-     * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
-     * activity M in the same task. Now, when reopening the task, T starts on top of M but then
-     * immediately finishes after, so we have to transfer T to M.
-     */
-    void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
-        final Task task = getTask();
-        for (int i = task.mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken fromToken = task.mChildren.get(i);
-            if (fromToken == this) {
-                return;
-            }
-            if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
-                return;
-            }
-        }
-    }
-
-    boolean transferStartingWindow(IBinder transferFrom) {
-        final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
-        if (fromToken == null) {
-            return false;
-        }
-
-        final WindowState tStartingWindow = fromToken.startingWindow;
-        if (tStartingWindow != null && fromToken.startingSurface != null) {
-            // In this case, the starting icon has already been displayed, so start
-            // letting windows get shown immediately without any more transitions.
-            getDisplayContent().mSkipAppTransitionAnimation = true;
-
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
-                    + " from %s to %s", tStartingWindow, fromToken, this);
-
-            final long origId = Binder.clearCallingIdentity();
-            try {
-                // Transfer the starting window over to the new token.
-                mStartingData = fromToken.mStartingData;
-                startingSurface = fromToken.startingSurface;
-                startingDisplayed = fromToken.startingDisplayed;
-                fromToken.startingDisplayed = false;
-                startingWindow = tStartingWindow;
-                reportedVisible = fromToken.reportedVisible;
-                fromToken.mStartingData = null;
-                fromToken.startingSurface = null;
-                fromToken.startingWindow = null;
-                fromToken.startingMoved = true;
-                tStartingWindow.mToken = this;
-                tStartingWindow.mAppToken = this;
-
-                ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                        "Removing starting %s from %s", tStartingWindow, fromToken);
-                fromToken.removeChild(tStartingWindow);
-                fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
-                fromToken.mHiddenSetFromTransferredStartingWindow = false;
-                addWindow(tStartingWindow);
-
-                // Propagate other interesting state between the tokens. If the old token is displayed,
-                // we should immediately force the new one to be displayed. If it is animating, we need
-                // to move that animation to the new one.
-                if (fromToken.allDrawn) {
-                    allDrawn = true;
-                    deferClearAllDrawn = fromToken.deferClearAllDrawn;
-                }
-                if (fromToken.firstWindowDrawn) {
-                    firstWindowDrawn = true;
-                }
-                if (!fromToken.isHidden()) {
-                    setHidden(false);
-                    hiddenRequested = false;
-                    mHiddenSetFromTransferredStartingWindow = true;
-                }
-                setClientHidden(fromToken.mClientHidden);
-
-                transferAnimation(fromToken);
-
-                // When transferring an animation, we no longer need to apply an animation to the
-                // the token we transfer the animation over. Thus, set this flag to indicate we've
-                // transferred the animation.
-                mUseTransferredAnimation = true;
-
-                mWmService.updateFocusedWindowLocked(
-                        UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
-                getDisplayContent().setLayoutNeeded();
-                mWmService.mWindowPlacerLocked.performSurfacePlacement();
-            } finally {
-                Binder.restoreCallingIdentity(origId);
-            }
-            return true;
-        } else if (fromToken.mStartingData != null) {
-            // The previous app was getting ready to show a
-            // starting window, but hasn't yet done so.  Steal it!
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                    "Moving pending starting from %s to %s", fromToken, this);
-            mStartingData = fromToken.mStartingData;
-            fromToken.mStartingData = null;
-            fromToken.startingMoved = true;
-            scheduleAddStartingWindow();
-            return true;
-        }
-
-        // TODO: Transfer thumbnail
-
-        return false;
-    }
-
-    boolean isLastWindow(WindowState win) {
-        return mChildren.size() == 1 && mChildren.get(0) == win;
-    }
-
-    @Override
-    void onAppTransitionDone() {
-        sendingToBottom = false;
-    }
-
-    /**
-     * We override because this class doesn't want its children affecting its reported orientation
-     * in anyway.
-     */
-    @Override
-    int getOrientation(int candidate) {
-        if (candidate == SCREEN_ORIENTATION_BEHIND) {
-            // Allow app to specify orientation regardless of its visibility state if the current
-            // candidate want us to use orientation behind. I.e. the visible app on-top of this one
-            // wants us to use the orientation of the app behind it.
-            return mOrientation;
-        }
-
-        // The {@link AppWindowToken} should only specify an orientation when it is not closing or
-        // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
-        // an Activity in another task being started in the wrong orientation during the transition.
-        if (!(sendingToBottom || getDisplayContent().mClosingApps.contains(this))
-                && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
-            return mOrientation;
-        }
-
-        return SCREEN_ORIENTATION_UNSET;
-    }
-
-    /** Returns the app's preferred orientation regardless of its currently visibility state. */
-    int getRequestedOrientation() {
-        return mOrientation;
-    }
-
-    /** @return {@code true} if the compatibility bounds is taking effect. */
-    boolean hasSizeCompatBounds() {
-        return mSizeCompatBounds != null;
-    }
-
-    @Override
-    float getSizeCompatScale() {
-        return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newParentConfig) {
-        final int prevWinMode = getWindowingMode();
-        mTmpPrevBounds.set(getBounds());
-        super.onConfigurationChanged(newParentConfig);
-
-        final Task task = getTask();
-        final Rect overrideBounds = getResolvedOverrideBounds();
-        if (task != null && !overrideBounds.isEmpty()
-                // If the changes come from change-listener, the incoming parent configuration is
-                // still the old one. Make sure their orientations are the same to reduce computing
-                // the compatibility bounds for the intermediate state.
-                && (task.mTaskRecord == null || task.mTaskRecord
-                        .getConfiguration().orientation == newParentConfig.orientation)) {
-            final Rect taskBounds = task.getBounds();
-            // Since we only center the activity horizontally, if only the fixed height is smaller
-            // than its container, the override bounds don't need to take effect.
-            if ((overrideBounds.width() != taskBounds.width()
-                    || overrideBounds.height() > taskBounds.height())) {
-                calculateCompatBoundsTransformation(newParentConfig);
-                updateSurfacePosition();
-            } else if (mSizeCompatBounds != null) {
-                mSizeCompatBounds = null;
-                mSizeCompatScale = 1f;
-                updateSurfacePosition();
-            }
-        }
-
-        final int winMode = getWindowingMode();
-
-        if (prevWinMode == winMode || mDisplayContent == null) {
-            return;
-        }
-
-        if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED
-                && !isHidden()) {
-            // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
-            // for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
-            final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
-            if (pinnedStack != null) {
-                final Rect stackBounds;
-                if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
-                    // We are animating the bounds, use the pre-animation bounds to save the snap
-                    // fraction
-                    stackBounds = pinnedStack.mPreAnimationBounds;
-                } else {
-                    // We skip the animation if the fullscreen configuration is not compatible, so
-                    // use the current bounds to calculate the saved snap fraction instead
-                    // (see PinnedActivityStack.skipResizeAnimation())
-                    stackBounds = mTmpRect;
-                    pinnedStack.getBounds(stackBounds);
-                }
-                mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(
-                        mActivityComponent, stackBounds);
-            }
-        } else if (shouldStartChangeTransition(prevWinMode, winMode)) {
-            initializeChangeTransition(mTmpPrevBounds);
-        }
-    }
-
-    private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
-        if (mWmService.mDisableTransitionAnimation
-                || !isVisible()
-                || getDisplayContent().mAppTransition.isTransitionSet()
-                || getSurfaceControl() == null) {
-            return false;
-        }
-        // Only do an animation into and out-of freeform mode for now. Other mode
-        // transition animations are currently handled by system-ui.
-        return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
-    }
-
-    /**
-     * Initializes a change transition. Because the app is visible already, there is a small period
-     * of time where the user can see the app content/window update before the transition starts.
-     * To prevent this, we immediately take a snapshot and place the app/snapshot into a leash which
-     * "freezes" the location/crop until the transition starts.
-     * <p>
-     * Here's a walk-through of the process:
-     * 1. Create a temporary leash ("interim-change-leash") and reparent the app to it.
-     * 2. Set the temporary leash's position/crop to the current state.
-     * 3. Create a snapshot and place that at the top of the leash to cover up content changes.
-     * 4. Once the transition is ready, it will reparent the app to the animation leash.
-     * 5. Detach the interim-change-leash.
-     */
-    private void initializeChangeTransition(Rect startBounds) {
-        mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
-                false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
-        mDisplayContent.mChangingApps.add(this);
-        mTransitStartRect.set(startBounds);
-
-        final SurfaceControl.Builder builder = makeAnimationLeash()
-                .setParent(getAnimationLeashParent())
-                .setName(getSurfaceControl() + " - interim-change-leash");
-        mTransitChangeLeash = builder.build();
-        Transaction t = getPendingTransaction();
-        t.setWindowCrop(mTransitChangeLeash, startBounds.width(), startBounds.height());
-        t.setPosition(mTransitChangeLeash, startBounds.left, startBounds.top);
-        t.show(mTransitChangeLeash);
-        t.reparent(getSurfaceControl(), mTransitChangeLeash);
-        onAnimationLeashCreated(t, mTransitChangeLeash);
-
-        // Skip creating snapshot if this transition is controlled by a remote animator which
-        // doesn't need it.
-        ArraySet<Integer> activityTypes = new ArraySet<>();
-        activityTypes.add(getActivityType());
-        RemoteAnimationAdapter adapter =
-                mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
-                        this, TRANSIT_TASK_CHANGE_WINDOWING_MODE, activityTypes);
-        if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
-            return;
-        }
-
-        Task task = getTask();
-        if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
-            SurfaceControl.ScreenshotGraphicBuffer snapshot =
-                    mWmService.mTaskSnapshotController.createTaskSnapshot(
-                            task, 1 /* scaleFraction */);
-            if (snapshot != null) {
-                mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
-                        snapshot.getGraphicBuffer(), true /* relative */);
-            }
-        }
-    }
-
-    boolean isInChangeTransition() {
-        return mTransitChangeLeash != null || AppTransition.isChangeTransit(mTransit);
-    }
-
-    @VisibleForTesting
-    AppWindowThumbnail getThumbnail() {
-        return mThumbnail;
-    }
-
-    /**
-     * Calculates the scale and offset to horizontal center the size compatibility bounds into the
-     * region which is available to application.
-     */
-    private void calculateCompatBoundsTransformation(Configuration newParentConfig) {
-        final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
-        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
-        final Rect viewportBounds = parentAppBounds != null ? parentAppBounds : parentBounds;
-        final Rect appBounds = getWindowConfiguration().getAppBounds();
-        final Rect contentBounds = appBounds != null ? appBounds : getResolvedOverrideBounds();
-        final float contentW = contentBounds.width();
-        final float contentH = contentBounds.height();
-        final float viewportW = viewportBounds.width();
-        final float viewportH = viewportBounds.height();
-        // Only allow to scale down.
-        mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
-                ? 1 : Math.min(viewportW / contentW, viewportH / contentH);
-        final int offsetX = (int) ((viewportW - contentW * mSizeCompatScale + 1) * 0.5f)
-                + viewportBounds.left;
-
-        if (mSizeCompatBounds == null) {
-            mSizeCompatBounds = new Rect();
-        }
-        mSizeCompatBounds.set(contentBounds);
-        mSizeCompatBounds.offsetTo(0, 0);
-        mSizeCompatBounds.scale(mSizeCompatScale);
-        // Ensure to align the top with the parent.
-        mSizeCompatBounds.top = parentBounds.top;
-        // The decor inset is included in height.
-        mSizeCompatBounds.bottom += viewportBounds.top;
-        mSizeCompatBounds.left += offsetX;
-        mSizeCompatBounds.right += offsetX;
-    }
-
-    @Override
-    public Rect getBounds() {
-        if (mSizeCompatBounds != null) {
-            return mSizeCompatBounds;
-        }
-        return super.getBounds();
-    }
-
-    @Override
-    public boolean matchParentBounds() {
-        if (super.matchParentBounds()) {
-            return true;
-        }
-        // An activity in size compatibility mode may have override bounds which equals to its
-        // parent bounds, so the exact bounds should also be checked.
-        final WindowContainer parent = getParent();
-        return parent == null || parent.getBounds().equals(getResolvedOverrideBounds());
-    }
-
-    @Override
-    void checkAppWindowsReadyToShow() {
-        if (allDrawn == mLastAllDrawn) {
-            return;
-        }
-
-        mLastAllDrawn = allDrawn;
-        if (!allDrawn) {
-            return;
-        }
-
-        // The token has now changed state to having all windows shown...  what to do, what to do?
-        if (mFreezingScreen) {
-            showAllWindowsLocked();
-            stopFreezingScreen(false, true);
-            ProtoLog.i(WM_DEBUG_ORIENTATION,
-                            "Setting mOrientationChangeComplete=true because wtoken %s "
-                                    + "numInteresting=%d numDrawn=%d",
-                            this, mNumInterestingWindows, mNumDrawnWindows);
-            // This will set mOrientationChangeComplete and cause a pass through layout.
-            setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
-                    "checkAppWindowsReadyToShow: freezingScreen");
-        } else {
-            setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
-
-            // We can now show all of the drawn windows!
-            if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
-                showAllWindowsLocked();
-            }
-        }
-    }
-
-    /**
-     * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
-     * child {@link WindowState}. A child is considered if it has been passed into
-     * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
-     * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
-     * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
-     *
-     * @return {@code true} If all children have been considered, {@code false}.
-     */
-    private boolean allDrawnStatesConsidered() {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final WindowState child = mChildren.get(i);
-            if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     *  Determines if the token has finished drawing. This should only be called from
-     *  {@link DisplayContent#applySurfaceChangesTransaction}
-     */
-    void updateAllDrawn() {
-        if (!allDrawn) {
-            // Number of drawn windows can be less when a window is being relaunched, wait for
-            // all windows to be launched and drawn for this token be considered all drawn.
-            final int numInteresting = mNumInterestingWindows;
-
-            // We must make sure that all present children have been considered (determined by
-            // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
-            // drawn.
-            if (numInteresting > 0 && allDrawnStatesConsidered()
-                    && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
-                if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
-                        + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
-                allDrawn = true;
-                // Force an additional layout pass where
-                // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
-                if (mDisplayContent != null) {
-                    mDisplayContent.setLayoutNeeded();
-                }
-                mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
-
-                // Notify the pinned stack upon all windows drawn. If there was an animation in
-                // progress then this signal will resume that animation.
-                final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
-                if (pinnedStack != null) {
-                    pinnedStack.onAllWindowsDrawn();
-                }
-            }
-        }
-    }
-
-    // Mostly implemented in ActivityRecord...
-    boolean keyDispatchingTimedOut(String reason, int windowPid) {
-        return false;
-    }
-
-    /**
-     * Updated this app token tracking states for interesting and drawn windows based on the window.
-     *
-     * @return Returns true if the input window is considered interesting and drawn while all the
-     *         windows in this app token where not considered drawn as of the last pass.
-     */
-    boolean updateDrawnWindowStates(WindowState w) {
-        w.setDrawnStateEvaluated(true /*evaluated*/);
-
-        if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
-            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
-                    + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
-        }
-
-        if (allDrawn && !mFreezingScreen) {
-            return false;
-        }
-
-        if (mLastTransactionSequence != mWmService.mTransactionSequence) {
-            mLastTransactionSequence = mWmService.mTransactionSequence;
-            mNumDrawnWindows = 0;
-            startingDisplayed = false;
-
-            // There is the main base application window, even if it is exiting, wait for it
-            mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
-        }
-
-        final WindowStateAnimator winAnimator = w.mWinAnimator;
-
-        boolean isInterestingAndDrawn = false;
-
-        if (!allDrawn && w.mightAffectAllDrawn()) {
-            if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
-                Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
-                        + ", isAnimationSet=" + isSelfAnimating());
-                if (!w.isDrawnLw()) {
-                    Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
-                            + " pv=" + w.isVisibleByPolicy()
-                            + " mDrawState=" + winAnimator.drawStateToString()
-                            + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
-                            + " a=" + isSelfAnimating());
-                }
-            }
-
-            if (w != startingWindow) {
-                if (w.isInteresting()) {
-                    // Add non-main window as interesting since the main app has already been added
-                    if (findMainWindow(false /* includeStartingApp */) != w) {
-                        mNumInterestingWindows++;
-                    }
-                    if (w.isDrawnLw()) {
-                        mNumDrawnWindows++;
-
-                        if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
-                            Slog.v(TAG, "tokenMayBeDrawn: "
-                                    + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
-                                    + " freezingScreen=" + mFreezingScreen
-                                    + " mAppFreezing=" + w.mAppFreezing);
-                        }
-
-                        isInterestingAndDrawn = true;
-                    }
-                }
-            } else if (w.isDrawnLw()) {
-                onStartingWindowDrawn(SystemClock.uptimeMillis());
-                startingDisplayed = true;
-            }
-        }
-
-        return isInterestingAndDrawn;
-    }
-
-    /** Called when the starting window for this container is drawn. */
-    private void onStartingWindowDrawn(long timestamp) {
-        synchronized (mAtmService.mGlobalLock) {
-            mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
-                    getWindowingMode(), timestamp);
-        }
-    }
-
-    void layoutLetterbox(WindowState winHint) {
-        final WindowState w = findMainWindow();
-        if (w == null || winHint != null && w != winHint) {
-            return;
-        }
-        final boolean surfaceReady = w.isDrawnLw()  // Regular case
-                || w.mWinAnimator.mSurfaceDestroyDeferred  // The preserved surface is still ready.
-                || w.isDragResizeChanged();  // Waiting for relayoutWindow to call preserveSurface.
-        final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
-        if (needsLetterbox) {
-            if (mLetterbox == null) {
-                mLetterbox = new Letterbox(() -> makeChildSurface(null),
-                        mWmService.mTransactionFactory);
-                mLetterbox.attachInput(w);
-            }
-            getPosition(mTmpPoint);
-            // Get the bounds of the "space-to-fill". In multi-window mode, the task-level
-            // represents this. In fullscreen-mode, the stack does (since the orientation letterbox
-            // is also applied to the task).
-            Rect spaceToFill = (inMultiWindowMode() || getStack() == null)
-                    ? getTask().getDisplayedBounds() : getStack().getDisplayedBounds();
-            mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
-        } else if (mLetterbox != null) {
-            mLetterbox.hide();
-        }
-    }
-
-    void updateLetterboxSurface(WindowState winHint) {
-        final WindowState w = findMainWindow();
-        if (w != winHint && winHint != null && w != null) {
-            return;
-        }
-        layoutLetterbox(winHint);
-        if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
-            mLetterbox.applySurfaceChanges(getPendingTransaction());
-        }
-    }
-
-    @Override
-    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
-        // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
-        // before the non-exiting app tokens. So, we skip the exiting app tokens here.
-        // TODO: Investigate if we need to continue to do this or if we can just process them
-        // in-order.
-        if (mIsExiting && !waitingForReplacement()) {
-            return false;
-        }
-        return forAllWindowsUnchecked(callback, traverseTopToBottom);
-    }
-
-    @Override
-    void forAllAppWindows(Consumer<AppWindowToken> callback) {
-        callback.accept(this);
-    }
-
-    boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
-            boolean traverseTopToBottom) {
-        return super.forAllWindows(callback, traverseTopToBottom);
-    }
-
-    @Override
-    AppWindowToken asAppWindowToken() {
-        // I am an app window token!
-        return this;
-    }
-
-    boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
-            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
-            IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
-        // If the display is frozen, we won't do anything until the actual window is
-        // displayed so there is no reason to put in the starting window.
-        if (!okToDisplay()) {
-            return false;
-        }
-
-        if (mStartingData != null) {
-            return false;
-        }
-
-        final WindowState mainWin = findMainWindow();
-        if (mainWin != null && mainWin.mWinAnimator.getShown()) {
-            // App already has a visible window...why would you want a starting window?
-            return false;
-        }
-
-        final ActivityManager.TaskSnapshot snapshot =
-                mWmService.mTaskSnapshotController.getSnapshot(
-                        getTask().mTaskId, getTask().mUserId,
-                        false /* restoreFromDisk */, false /* reducedResolution */);
-        final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
-                allowTaskSnapshot, activityCreated, fromRecents, snapshot);
-
-        if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
-            return createSnapshot(snapshot);
-        }
-
-        // If this is a translucent window, then don't show a starting window -- the current
-        // effect (a full-screen opaque starting window that fades away to the real contents
-        // when it is ready) does not work for this.
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
-        if (theme != 0) {
-            AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
-                    com.android.internal.R.styleable.Window,
-                    mWmService.mCurrentUserId);
-            if (ent == null) {
-                // Whoops!  App doesn't exist. Um. Okay. We'll just pretend like we didn't
-                // see that.
-                return false;
-            }
-            final boolean windowIsTranslucent = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowIsTranslucent, false);
-            final boolean windowIsFloating = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowIsFloating, false);
-            final boolean windowShowWallpaper = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowShowWallpaper, false);
-            final boolean windowDisableStarting = ent.array.getBoolean(
-                    com.android.internal.R.styleable.Window_windowDisablePreview, false);
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
-                        windowIsTranslucent, windowIsFloating, windowShowWallpaper);
-            if (windowIsTranslucent) {
-                return false;
-            }
-            if (windowIsFloating || windowDisableStarting) {
-                return false;
-            }
-            if (windowShowWallpaper) {
-                if (getDisplayContent().mWallpaperController
-                        .getWallpaperTarget() == null) {
-                    // If this theme is requesting a wallpaper, and the wallpaper
-                    // is not currently visible, then this effectively serves as
-                    // an opaque window and our starting window transition animation
-                    // can still work.  We just need to make sure the starting window
-                    // is also showing the wallpaper.
-                    windowFlags |= FLAG_SHOW_WALLPAPER;
-                } else {
-                    return false;
-                }
-            }
-        }
-
-        if (transferStartingWindow(transferFrom)) {
-            return true;
-        }
-
-        // There is no existing starting window, and we don't want to create a splash screen, so
-        // that's it!
-        if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
-            return false;
-        }
-
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
-        mStartingData = new SplashScreenStartingData(mWmService, pkg,
-                theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
-                getMergedOverrideConfiguration());
-        scheduleAddStartingWindow();
-        return true;
-    }
-
-
-    private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
-        if (snapshot == null) {
-            return false;
-        }
-
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
-        mStartingData = new SnapshotStartingData(mWmService, snapshot);
-        scheduleAddStartingWindow();
-        return true;
-    }
-
-    void scheduleAddStartingWindow() {
-        // Note: we really want to do sendMessageAtFrontOfQueue() because we
-        // want to process the message ASAP, before any other queued
-        // messages.
-        if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
-            mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
-        }
-    }
-
-    private class AddStartingWindow implements Runnable {
-
-        @Override
-        public void run() {
-            // Can be accessed without holding the global lock
-            final StartingData startingData;
-            synchronized (mWmService.mGlobalLock) {
-                // There can only be one adding request, silly caller!
-                mWmService.mAnimationHandler.removeCallbacks(this);
-
-                if (mStartingData == null) {
-                    // Animation has been canceled... do nothing.
-                    ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                            "startingData was nulled out before handling"
-                                + " mAddStartingWindow: %s", AppWindowToken.this);
-                    return;
-                }
-                startingData = mStartingData;
-            }
-
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
-                    this, startingData);
-
-
-            WindowManagerPolicy.StartingSurface surface = null;
-            try {
-                surface = startingData.createStartingSurface(AppWindowToken.this);
-            } catch (Exception e) {
-                Slog.w(TAG, "Exception when adding starting window", e);
-            }
-            if (surface != null) {
-                boolean abort = false;
-                synchronized (mWmService.mGlobalLock) {
-                    // If the window was successfully added, then
-                    // we need to remove it.
-                    if (removed || mStartingData == null) {
-                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                                "Aborted starting %s: removed=%b startingData=%s",
-                                    AppWindowToken.this, removed, mStartingData);
-
-                        startingWindow = null;
-                        mStartingData = null;
-                        abort = true;
-                    } else {
-                        startingSurface = surface;
-                    }
-                    if (!abort) {
-                        ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                                "Added starting %s: startingWindow=%s startingView=%s",
-                                AppWindowToken.this, startingWindow, startingSurface);
-                    }
-                }
-                if (abort) {
-                    surface.remove();
-                }
-            } else {
-                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
-                        AppWindowToken.this);
-            }
-        }
-    }
-
-    private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
-
-    private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
-            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
-            ActivityManager.TaskSnapshot snapshot) {
-        if (getDisplayContent().mAppTransition.getAppTransition()
-                == TRANSIT_DOCK_TASK_FROM_RECENTS) {
-            // TODO(b/34099271): Remove this statement to add back the starting window and figure
-            // out why it causes flickering, the starting window appears over the thumbnail while
-            // the docked from recents transition occurs
-            return STARTING_WINDOW_TYPE_NONE;
-        } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
-            return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-        } else if (taskSwitch && allowTaskSnapshot) {
-            if (mWmService.mLowRamTaskSnapshotsAndRecents) {
-                // For low RAM devices, we use the splash screen starting window instead of the
-                // task snapshot starting window.
-                return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-            }
-            return snapshot == null ? STARTING_WINDOW_TYPE_NONE
-                    : snapshotOrientationSameAsTask(snapshot) || fromRecents
-                            ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-        } else {
-            return STARTING_WINDOW_TYPE_NONE;
-        }
-    }
-
-
-    private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
-        if (snapshot == null) {
-            return false;
-        }
-        return getTask().getConfiguration().orientation == snapshot.getOrientation();
-    }
-
-    void removeStartingWindow() {
-        if (startingWindow == null) {
-            if (mStartingData != null) {
-                // Starting window has not been added yet, but it is scheduled to be added.
-                // Go ahead and cancel the request.
-                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
-                mStartingData = null;
-            }
-            return;
-        }
-
-        final WindowManagerPolicy.StartingSurface surface;
-        if (mStartingData != null) {
-            surface = startingSurface;
-            mStartingData = null;
-            startingSurface = null;
-            startingWindow = null;
-            startingDisplayed = false;
-            if (surface == null) {
-                ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                        "startingWindow was set but startingSurface==null, couldn't "
-                            + "remove");
-
-                return;
-            }
-        } else {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
-                    "Tried to remove starting window but startingWindow was null: %s",
-                        this);
-            return;
-        }
-
-        ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
-                    + " startingView=%s Callers=%s",
-                    this, startingWindow, startingSurface, Debug.getCallers(5));
-
-
-        // Use the same thread to remove the window as we used to add it, as otherwise we end up
-        // with things in the view hierarchy being called from different threads.
-        mWmService.mAnimationHandler.post(() -> {
-            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
-            try {
-                surface.remove();
-            } catch (Exception e) {
-                Slog.w(TAG_WM, "Exception when removing starting window", e);
-            }
-        });
-    }
-
-    @Override
-    boolean fillsParent() {
-        return occludesParent();
-    }
-
-    /** Returns true if this activity is opaque and fills the entire space of this task. */
-    boolean occludesParent() {
-        return mOccludesParent;
-    }
-
-    boolean setOccludesParent(boolean occludesParent) {
-        final boolean changed = occludesParent != mOccludesParent;
-        mOccludesParent = occludesParent;
-        setMainWindowOpaque(occludesParent);
-        mWmService.mWindowPlacerLocked.requestTraversal();
-        return changed;
-    }
-
-    void setMainWindowOpaque(boolean isOpaque) {
-        final WindowState win = findMainWindow();
-        if (win == null) {
-            return;
-        }
-        isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
-        win.mWinAnimator.setOpaqueLocked(isOpaque);
-    }
-
-    boolean containsDismissKeyguardWindow() {
-        // Window state is transient during relaunch. We are not guaranteed to be frozen during the
-        // entirety of the relaunch.
-        if (isRelaunching()) {
-            return mLastContainsDismissKeyguardWindow;
-        }
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    boolean containsShowWhenLockedWindow() {
-        // When we are relaunching, it is possible for us to be unfrozen before our previous
-        // windows have been added back. Using the cached value ensures that our previous
-        // showWhenLocked preference is honored until relaunching is complete.
-        if (isRelaunching()) {
-            return mLastContainsShowWhenLockedWindow;
-        }
-
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
-            if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    void setShowWhenLocked(boolean showWhenLocked) {
-        mShowWhenLocked = showWhenLocked;
-        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
-                0 /* configChanges */, false /* preserveWindows */);
-    }
-
-    void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
-        mInheritShownWhenLocked = inheritShowWhenLocked;
-        mAtmService.mRootActivityContainer.ensureActivitiesVisible(null /* starting */,
-                0 /* configChanges */, false /* preserveWindows */);
-    }
-
-    /**
-     * @return {@code true} if the activity windowing mode is not
-     *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
-     *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
-     *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
-     *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
-     *         conditions a) above.
-     *         Multi-windowing mode will be exited if {@code true} is returned.
-     */
-    boolean canShowWhenLocked() {
-        if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
-            return true;
-        } else if (mInheritShownWhenLocked) {
-            final AppWindowToken r = getActivityBelow();
-            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
-                    || r.containsShowWhenLockedWindow());
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
-     * such activity exists.
-     */
-    @Nullable
-    private AppWindowToken getActivityBelow() {
-        final Task task = getTask();
-        final int pos = task.mChildren.indexOf(this);
-        if (pos == -1) {
-            throw new IllegalStateException("Activity not found in its task");
-        }
-        return pos == 0 ? null : task.getChildAt(pos - 1);
-    }
-
-    void setTurnScreenOn(boolean turnScreenOn) {
-        mTurnScreenOn = turnScreenOn;
-    }
-
-    /** Mostly implemented in ActivityRecord. */
-    boolean canTurnScreenOn() {
-        return mTurnScreenOn;
-    }
-
-    boolean getTurnScreenOnFlag() {
-        return mTurnScreenOn;
-    }
-
-    void checkKeyguardFlagsChanged() {
-        final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
-        final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
-        if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
-                || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
-            mWmService.notifyKeyguardFlagsChanged(null /* callback */,
-                    getDisplayContent().getDisplayId());
-        }
-        mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
-        mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
-    }
-
-    WindowState getImeTargetBelowWindow(WindowState w) {
-        final int index = mChildren.indexOf(w);
-        if (index > 0) {
-            final WindowState target = mChildren.get(index - 1);
-            if (target.canBeImeTarget()) {
-                return target;
-            }
-        }
-        return null;
-    }
-
-    WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
-        WindowState candidate = null;
-        for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
-            final WindowState w = mChildren.get(i);
-            if (w.mRemoved) {
-                continue;
-            }
-            if (candidate == null) {
-                candidate = w;
-            }
-        }
-        return candidate;
-    }
-
-    /**
-     * See {@link Activity#setDisablePreviewScreenshots}.
-     */
-    void setDisablePreviewScreenshots(boolean disable) {
-        mDisablePreviewScreenshots = disable;
-    }
-
-    /**
-     * Sets whether the current launch can turn the screen on.
-     * @see #currentLaunchCanTurnScreenOn()
-     */
-    void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
-        mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
-    }
-
-    /**
-     * Indicates whether the current launch can turn the screen on. This is to prevent multiple
-     * relayouts from turning the screen back on. The screen should only turn on at most
-     * once per activity resume.
-     * <p>
-     * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
-     * or {@link ActivityRecord#canTurnScreenOn} is set.
-     *
-     * @return {@code true} if the activity is ready to turn on the screen.
-     */
-    boolean currentLaunchCanTurnScreenOn() {
-        return mCurrentLaunchCanTurnScreenOn;
-    }
-
-    /**
-     * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
-     * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
-     * we can't take a snapshot for other reasons, for example, if we have a secure window.
-     *
-     * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
-     *         screenshot.
-     */
-    boolean shouldUseAppThemeSnapshot() {
-        return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
-                true /* topToBottom */);
-    }
-
-    SurfaceControl getAppAnimationLayer() {
-        return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
-                : needsZBoost() ? ANIMATION_LAYER_BOOSTED
-                : ANIMATION_LAYER_STANDARD);
-    }
-
-    @Override
-    public SurfaceControl getAnimationLeashParent() {
-        // For transitions in the pinned stack (menu activity) we just let them occur as a child
-        // of the pinned stack.
-        // All normal app transitions take place in an animation layer which is below the pinned
-        // stack but may be above the parent stacks of the given animating apps by default. When
-        // a new hierarchical animation is enabled, we just let them occur as a child of the parent
-        // stack, i.e. the hierarchy of the surfaces is unchanged.
-        if (inPinnedWindowingMode()) {
-            return getStack().getSurfaceControl();
-        } else if (WindowManagerService.sHierarchicalAnimations) {
-            return super.getAnimationLeashParent();
-        } else {
-            return getAppAnimationLayer();
-        }
-    }
-
-
-    @VisibleForTesting
-    boolean shouldAnimate(int transit) {
-        final boolean isSplitScreenPrimary =
-                getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-        final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
-
-        // Don't animate while the task runs recents animation but only if we are in the mode
-        // where we cancel with deferred screenshot, which means that the controller has
-        // transformed the task.
-        final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
-        if (controller != null && controller.isAnimatingTask(getTask())
-                && controller.shouldDeferCancelUntilNextTransition()) {
-            return false;
-        }
-
-        // We animate always if it's not split screen primary, and only some special cases in split
-        // screen primary because it causes issues with stack clipping when we run an un-minimize
-        // animation at the same time.
-        return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
-    }
-
-    /**
-     * Creates a layer to apply crop to an animation.
-     */
-    private SurfaceControl createAnimationBoundsLayer(Transaction t) {
-        ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
-        final SurfaceControl.Builder builder = makeAnimationLeash()
-                .setParent(getAnimationLeashParent())
-                .setName(getSurfaceControl() + " - animation-bounds");
-        final SurfaceControl boundsLayer = builder.build();
-        t.show(boundsLayer);
-        return boundsLayer;
-    }
-
-    @Override
-    Rect getDisplayedBounds() {
-        final Task task = getTask();
-        if (task != null) {
-            final Rect overrideDisplayedBounds = task.getOverrideDisplayedBounds();
-            if (!overrideDisplayedBounds.isEmpty()) {
-                return overrideDisplayedBounds;
-            }
-        }
-        return getBounds();
-    }
-
-    @VisibleForTesting
-    Rect getAnimationBounds(int appStackClipMode) {
-        if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
-            // Using the stack bounds here effectively applies the clipping before animation.
-            return getStack().getBounds();
-        }
-        // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
-        // included in the animation.
-        return getTask() != null ? getTask().getBounds() : getBounds();
-    }
-
-    boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
-            boolean isVoiceInteraction) {
-
-        if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
-            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
-                    "applyAnimation: transition animation is disabled or skipped. "
-                            + "atoken=%s", this);
-            cancelAnimation();
-            return false;
-        }
-
-        // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
-        // to animate and it can cause strange artifacts when we unfreeze the display if some
-        // different animation is running.
-        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
-        if (okToAnimate()) {
-            final AnimationAdapter adapter;
-            AnimationAdapter thumbnailAdapter = null;
-
-            final int appStackClipMode =
-                    getDisplayContent().mAppTransition.getAppStackClipMode();
-
-            // Separate position and size for use in animators.
-            mTmpRect.set(getAnimationBounds(appStackClipMode));
-            mTmpPoint.set(mTmpRect.left, mTmpRect.top);
-            mTmpRect.offsetTo(0, 0);
-
-            final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
-                    && getDisplayContent().mChangingApps.contains(this);
-
-            // Delaying animation start isn't compatible with remote animations at all.
-            if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
-                    && !mSurfaceAnimator.isAnimationStartDelayed()) {
-                RemoteAnimationRecord adapters =
-                        getDisplayContent().mAppTransition.getRemoteAnimationController()
-                                .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
-                                        (isChanging ? mTransitStartRect : null));
-                adapter = adapters.mAdapter;
-                thumbnailAdapter = adapters.mThumbnailAdapter;
-            } else if (isChanging) {
-                final float durationScale = mWmService.getTransitionAnimationScaleLocked();
-                mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
-                adapter = new LocalAnimationAdapter(
-                        new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
-                                getDisplayContent().getDisplayInfo(), durationScale,
-                                true /* isAppAnimation */, false /* isThumbnail */),
-                        mWmService.mSurfaceAnimationRunner);
-                if (mThumbnail != null) {
-                    thumbnailAdapter = new LocalAnimationAdapter(
-                            new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
-                                    getDisplayContent().getDisplayInfo(), durationScale,
-                                    true /* isAppAnimation */, true /* isThumbnail */),
-                            mWmService.mSurfaceAnimationRunner);
-                }
-                mTransit = transit;
-                mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
-            } else {
-                mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
-
-                final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
-                if (a != null) {
-                    // Only apply corner radius to animation if we're not in multi window mode.
-                    // We don't want rounded corners when in pip or split screen.
-                    final float windowCornerRadius = !inMultiWindowMode()
-                            ? getDisplayContent().getWindowCornerRadius()
-                            : 0;
-                    adapter = new LocalAnimationAdapter(
-                            new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
-                                    getDisplayContent().mAppTransition.canSkipFirstFrame(),
-                                    appStackClipMode,
-                                    true /* isAppAnimation */,
-                                    windowCornerRadius),
-                            mWmService.mSurfaceAnimationRunner);
-                    if (a.getZAdjustment() == Animation.ZORDER_TOP) {
-                        mNeedsZBoost = true;
-                    }
-                    mTransit = transit;
-                    mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
-                } else {
-                    adapter = null;
-                }
-            }
-            if (adapter != null) {
-                startAnimation(getPendingTransaction(), adapter, !isVisible());
-                if (adapter.getShowWallpaper()) {
-                    mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-                }
-                if (thumbnailAdapter != null) {
-                    mThumbnail.startAnimation(
-                            getPendingTransaction(), thumbnailAdapter, !isVisible());
-                }
-            }
-        } else {
-            cancelAnimation();
-        }
-        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-
-        return isReallyAnimating();
-    }
-
-    private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
-            boolean isVoiceInteraction) {
-        final DisplayContent displayContent = getTask().getDisplayContent();
-        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final int width = displayInfo.appWidth;
-        final int height = displayInfo.appHeight;
-        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
-                "applyAnimation: atoken=%s", this);
-
-        // Determine the visible rect to calculate the thumbnail clip
-        final WindowState win = findMainWindow();
-        final Rect frame = new Rect(0, 0, width, height);
-        final Rect displayFrame = new Rect(0, 0,
-                displayInfo.logicalWidth, displayInfo.logicalHeight);
-        final Rect insets = new Rect();
-        final Rect stableInsets = new Rect();
-        Rect surfaceInsets = null;
-        final boolean freeform = win != null && win.inFreeformWindowingMode();
-        if (win != null) {
-            // Containing frame will usually cover the whole screen, including dialog windows.
-            // For freeform workspace windows it will not cover the whole screen and it also
-            // won't exactly match the final freeform window frame (e.g. when overlapping with
-            // the status bar). In that case we need to use the final frame.
-            if (freeform) {
-                frame.set(win.getFrameLw());
-            } else if (win.isLetterboxedAppWindow()) {
-                frame.set(getTask().getBounds());
-            } else if (win.isDockedResizing()) {
-                // If we are animating while docked resizing, then use the stack bounds as the
-                // animation target (which will be different than the task bounds)
-                frame.set(getTask().getParent().getBounds());
-            } else {
-                frame.set(win.getContainingFrame());
-            }
-            surfaceInsets = win.getAttrs().surfaceInsets;
-            // XXX(b/72757033): These are insets relative to the window frame, but we're really
-            // interested in the insets relative to the frame we chose in the if-blocks above.
-            win.getContentInsets(insets);
-            win.getStableInsets(stableInsets);
-        }
-
-        if (mLaunchTaskBehind) {
-            // Differentiate the two animations. This one which is briefly on the screen
-            // gets the !enter animation, and the other activity which remains on the
-            // screen gets the enter animation. Both appear in the mOpeningApps set.
-            enter = false;
-        }
-        ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
-                "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
-                        + "surfaceInsets=%s",
-                AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
-        final Configuration displayConfig = displayContent.getConfiguration();
-        final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
-                displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
-                surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
-        if (a != null) {
-            if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
-            final int containingWidth = frame.width();
-            final int containingHeight = frame.height();
-            a.initialize(containingWidth, containingHeight, width, height);
-            a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
-        }
-        return a;
-    }
-
-    @Override
-    public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
-        return mAnimatingAppWindowTokenRegistry != null
-                && mAnimatingAppWindowTokenRegistry.notifyAboutToFinish(
-                        this, endDeferFinishCallback);
-    }
-
-    @Override
-    public void onAnimationLeashLost(Transaction t) {
-        super.onAnimationLeashLost(t);
-        if (mAnimationBoundsLayer != null) {
-            t.remove(mAnimationBoundsLayer);
-            mAnimationBoundsLayer = null;
-        }
-
-        if (mAnimatingAppWindowTokenRegistry != null) {
-            mAnimatingAppWindowTokenRegistry.notifyFinished(this);
-        }
-    }
-
-    @Override
-    protected void setLayer(Transaction t, int layer) {
-        if (!mSurfaceAnimator.hasLeash()) {
-            t.setLayer(mSurfaceControl, layer);
-        }
-    }
-
-    @Override
-    protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
-        if (!mSurfaceAnimator.hasLeash()) {
-            t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
-        }
-    }
-
-    @Override
-    protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
-        if (!mSurfaceAnimator.hasLeash()) {
-            t.reparent(mSurfaceControl, newParent);
-        }
-    }
-
-    @Override
-    public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
-        // The leash is parented to the animation layer. We need to preserve the z-order by using
-        // the prefix order index, but we boost if necessary.
-        int layer = 0;
-        if (!inPinnedWindowingMode()) {
-            layer = getPrefixOrderIndex();
-        } else {
-            // Pinned stacks have animations take place within themselves rather than an animation
-            // layer so we need to preserve the order relative to the stack (e.g. the order of our
-            // task/parent).
-            layer = getParent().getPrefixOrderIndex();
-        }
-
-        if (mNeedsZBoost) {
-            layer += Z_BOOST_BASE;
-        }
-        if (!mNeedsAnimationBoundsLayer) {
-            t.setLayer(leash, layer);
-        }
-
-        final DisplayContent dc = getDisplayContent();
-        dc.assignStackOrdering();
-
-        if (leash == mTransitChangeLeash) {
-            // This is a temporary state so skip any animation notifications
-            return;
-        } else if (mTransitChangeLeash != null) {
-            // unparent mTransitChangeLeash for clean-up
-            clearChangeLeash(t, false /* cancel */);
-        }
-
-        if (mAnimatingAppWindowTokenRegistry != null) {
-            mAnimatingAppWindowTokenRegistry.notifyStarting(this);
-        }
-
-        // If the animation needs to be cropped then an animation bounds layer is created as a child
-        // of the pinned stack or animation layer. The leash is then reparented to this new layer.
-        if (mNeedsAnimationBoundsLayer) {
-            mTmpRect.setEmpty();
-            final Task task = getTask();
-            if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
-                    getTransit(), task)) {
-                task.getBounds(mTmpRect);
-            } else {
-                final TaskStack stack = getStack();
-                if (stack == null) {
-                    return;
-                }
-                // Set clip rect to stack bounds.
-                stack.getBounds(mTmpRect);
-            }
-            mAnimationBoundsLayer = createAnimationBoundsLayer(t);
-
-            // Crop to stack bounds.
-            t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
-            t.setLayer(mAnimationBoundsLayer, layer);
-
-            // Reparent leash to animation bounds layer.
-            t.reparent(leash, mAnimationBoundsLayer);
-        }
-    }
-
-    /**
-     * This must be called while inside a transaction.
-     */
-    void showAllWindowsLocked() {
-        forAllWindows(windowState -> {
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
-            windowState.performShowLocked();
-        }, false /* traverseTopToBottom */);
-    }
-
-    @Override
-    protected void onAnimationFinished() {
-        super.onAnimationFinished();
-
-        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
-        mTransit = TRANSIT_UNSET;
-        mTransitFlags = 0;
-        mNeedsZBoost = false;
-        mNeedsAnimationBoundsLayer = false;
-
-        setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
-                "AppWindowToken");
-
-        clearThumbnail();
-        setClientHidden(isHidden() && hiddenRequested);
-
-        getDisplayContent().computeImeTargetIfNeeded(this);
-
-        if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
-                + ": reportedVisible=" + reportedVisible
-                + " okToDisplay=" + okToDisplay()
-                + " okToAnimate=" + okToAnimate()
-                + " startingDisplayed=" + startingDisplayed);
-
-        // clean up thumbnail window
-        if (mThumbnail != null) {
-            mThumbnail.destroy();
-            mThumbnail = null;
-        }
-
-        // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
-        // traverse the copy.
-        final ArrayList<WindowState> children = new ArrayList<>(mChildren);
-        children.forEach(WindowState::onExitAnimationDone);
-
-        getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
-        scheduleAnimation();
-
-        if (mAtmService.mRootActivityContainer.allResumedActivitiesIdle()
-                || mAtmService.mStackSupervisor.isStoppingNoHistoryActivity()) {
-            // If all activities are already idle or there is an activity that must be
-            // stopped immediately after visible, then we now need to make sure we perform
-            // the full stop of this activity. This is because we won't do that while they are still
-            // waiting for the animation to finish.
-            if (mAtmService.mStackSupervisor.mStoppingActivities.contains(this)) {
-                mAtmService.mStackSupervisor.scheduleIdleLocked();
-            }
-        } else {
-            // Instead of doing the full stop routine here, let's just hide any activities
-            // we now can, and let them stop when the normal idle happens.
-            mAtmService.mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
-                    false /* remove */, true /* processPausingActivities */);
-        }
-        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-    }
-
-    @Override
-    boolean isAppAnimating() {
-        return isSelfAnimating();
-    }
-
-    @Override
-    boolean isSelfAnimating() {
-        // If we are about to start a transition, we also need to be considered animating.
-        return isWaitingForTransitionStart() || isReallyAnimating();
-    }
-
-    /**
-     * @return True if and only if we are actually running an animation. Note that
-     *         {@link #isSelfAnimating} also returns true if we are waiting for an animation to
-     *         start.
-     */
-    private boolean isReallyAnimating() {
-        return super.isSelfAnimating();
-    }
-
-    /**
-     * @param cancel {@code true} if clearing the leash due to cancelling instead of transferring
-     *                            to another leash.
-     */
-    private void clearChangeLeash(Transaction t, boolean cancel) {
-        if (mTransitChangeLeash == null) {
-            return;
-        }
-        if (cancel) {
-            clearThumbnail();
-            SurfaceControl sc = getSurfaceControl();
-            SurfaceControl parentSc = getParentSurfaceControl();
-            // Don't reparent if surface is getting destroyed
-            if (parentSc != null && sc != null) {
-                t.reparent(sc, getParentSurfaceControl());
-            }
-        }
-        t.hide(mTransitChangeLeash);
-        t.remove(mTransitChangeLeash);
-        mTransitChangeLeash = null;
-        if (cancel) {
-            onAnimationLeashLost(t);
-        }
-    }
-
-    @Override
-    void cancelAnimation() {
-        cancelAnimationOnly();
-        clearThumbnail();
-        clearChangeLeash(getPendingTransaction(), true /* cancel */);
-    }
-
-    /**
-     * This only cancels the animation. It doesn't do other teardown like cleaning-up thumbnail
-     * or interim leashes.
-     * <p>
-     * Used when canceling in preparation for starting a new animation.
-     */
-    void cancelAnimationOnly() {
-        super.cancelAnimation();
-    }
-
-    boolean isWaitingForTransitionStart() {
-        final DisplayContent dc = getDisplayContent();
-        // TODO: Test for null can be removed once unification is done.
-        if (dc == null) return false;
-        return dc.mAppTransition.isTransitionSet()
-                && (dc.mOpeningApps.contains(this)
-                    || dc.mClosingApps.contains(this)
-                    || dc.mChangingApps.contains(this));
-    }
-
-    public int getTransit() {
-        return mTransit;
-    }
-
-    int getTransitFlags() {
-        return mTransitFlags;
-    }
-
-    void attachThumbnailAnimation() {
-        if (!isReallyAnimating()) {
-            return;
-        }
-        final int taskId = getTask().mTaskId;
-        final GraphicBuffer thumbnailHeader =
-                getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
-        if (thumbnailHeader == null) {
-            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId);
-            return;
-        }
-        clearThumbnail();
-        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
-                this, thumbnailHeader);
-        mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
-    }
-
-    /**
-     * Attaches a surface with a thumbnail for the
-     * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
-     */
-    void attachCrossProfileAppsThumbnailAnimation() {
-        if (!isReallyAnimating()) {
-            return;
-        }
-        clearThumbnail();
-
-        final WindowState win = findMainWindow();
-        if (win == null) {
-            return;
-        }
-        final Rect frame = win.getFrameLw();
-        final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
-                ? R.drawable.ic_account_circle
-                : R.drawable.ic_corp_badge;
-        final GraphicBuffer thumbnail =
-                getDisplayContent().mAppTransition
-                        .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
-        if (thumbnail == null) {
-            return;
-        }
-        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
-                getPendingTransaction(), this, thumbnail);
-        final Animation animation =
-                getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
-                        win.getFrameLw());
-        mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
-                frame.top));
-    }
-
-    private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-
-        // If this is a multi-window scenario, we use the windows frame as
-        // destination of the thumbnail header animation. If this is a full screen
-        // window scenario, we use the whole display as the target.
-        WindowState win = findMainWindow();
-        Rect appRect = win != null ? win.getContentFrameLw() :
-                new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
-        final Rect insets = win != null ? win.getContentInsets() : null;
-        final Configuration displayConfig = mDisplayContent.getConfiguration();
-        return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
-                appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
-                displayConfig.orientation);
-    }
-
-    private void clearThumbnail() {
-        if (mThumbnail == null) {
-            return;
-        }
-        mThumbnail.destroy();
-        mThumbnail = null;
-    }
-
-    void registerRemoteAnimations(RemoteAnimationDefinition definition) {
-        mRemoteAnimationDefinition = definition;
-    }
-
-    RemoteAnimationDefinition getRemoteAnimationDefinition() {
-        return mRemoteAnimationDefinition;
-    }
-
-    @Override
-    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
-        super.dump(pw, prefix, dumpAll);
-        if (appToken != null) {
-            pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
-        }
-        pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
-        pw.print(prefix); pw.print("task="); pw.println(getTask());
-        pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
-                pw.print(" mOrientation="); pw.println(mOrientation);
-        pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
-            + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
-            + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
-        if (paused) {
-            pw.print(prefix); pw.print("paused="); pw.println(paused);
-        }
-        if (mAppStopped) {
-            pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
-        }
-        if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
-                || allDrawn || mLastAllDrawn) {
-            pw.print(prefix); pw.print("mNumInterestingWindows=");
-                    pw.print(mNumInterestingWindows);
-                    pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
-                    pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
-                    pw.print(" allDrawn="); pw.print(allDrawn);
-                    pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
-                    pw.println(")");
-        }
-        if (inPendingTransaction) {
-            pw.print(prefix); pw.print("inPendingTransaction=");
-                    pw.println(inPendingTransaction);
-        }
-        if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
-            pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
-                    pw.print(" removed="); pw.print(removed);
-                    pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
-                    pw.print(" mIsExiting="); pw.println(mIsExiting);
-        }
-        if (startingWindow != null || startingSurface != null
-                || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
-            pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
-                    pw.print(" startingSurface="); pw.print(startingSurface);
-                    pw.print(" startingDisplayed="); pw.print(startingDisplayed);
-                    pw.print(" startingMoved="); pw.print(startingMoved);
-                    pw.println(" mHiddenSetFromTransferredStartingWindow="
-                            + mHiddenSetFromTransferredStartingWindow);
-        }
-        if (!mFrozenBounds.isEmpty()) {
-            pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
-            pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
-        }
-        if (mPendingRelaunchCount != 0) {
-            pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
-        }
-        if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
-            pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
-                    + mSizeCompatBounds);
-        }
-        if (mRemovingFromDisplay) {
-            pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
-        }
-    }
-
-    @Override
-    void setHidden(boolean hidden) {
-        super.setHidden(hidden);
-        scheduleAnimation();
-    }
-
-    @Override
-    void prepareSurfaces() {
-        // isSelfAnimating also returns true when we are about to start a transition, so we need
-        // to check super here.
-        final boolean reallyAnimating = super.isSelfAnimating();
-        final boolean show = !isHidden() || reallyAnimating;
-
-        if (mSurfaceControl != null) {
-            if (show && !mLastSurfaceShowing) {
-                getPendingTransaction().show(mSurfaceControl);
-            } else if (!show && mLastSurfaceShowing) {
-                getPendingTransaction().hide(mSurfaceControl);
-            }
-        }
-        if (mThumbnail != null) {
-            mThumbnail.setShowing(getPendingTransaction(), show);
-        }
-        mLastSurfaceShowing = show;
-        super.prepareSurfaces();
-    }
-
-    /**
-     * @return Whether our {@link #getSurfaceControl} is currently showing.
-     */
-    boolean isSurfaceShowing() {
-        return mLastSurfaceShowing;
-    }
-
-    boolean isFreezingScreen() {
-        return mFreezingScreen;
-    }
-
-    @Override
-    boolean needsZBoost() {
-        return mNeedsZBoost || super.needsZBoost();
-    }
-
-    @CallSuper
-    @Override
-    public void writeToProto(ProtoOutputStream proto, long fieldId,
-            @WindowTraceLogLevel int logLevel) {
-        // Critical log level logs only visible elements to mitigate performance overheard
-        if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
-            return;
-        }
-
-        final long token = proto.start(fieldId);
-        writeNameToProto(proto, NAME);
-        super.writeToProto(proto, WINDOW_TOKEN, logLevel);
-        proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
-        proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
-        proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
-        if (mThumbnail != null){
-            mThumbnail.writeToProto(proto, THUMBNAIL);
-        }
-        proto.write(FILLS_PARENT, mOccludesParent);
-        proto.write(APP_STOPPED, mAppStopped);
-        proto.write(HIDDEN_REQUESTED, hiddenRequested);
-        proto.write(CLIENT_HIDDEN, mClientHidden);
-        proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
-        proto.write(REPORTED_DRAWN, reportedDrawn);
-        proto.write(REPORTED_VISIBLE, reportedVisible);
-        proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
-        proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
-        proto.write(ALL_DRAWN, allDrawn);
-        proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
-        proto.write(REMOVED, removed);
-        if (startingWindow != null) {
-            startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
-        }
-        proto.write(STARTING_DISPLAYED, startingDisplayed);
-        proto.write(STARTING_MOVED, startingMoved);
-        proto.write(HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW,
-                mHiddenSetFromTransferredStartingWindow);
-        for (Rect bounds : mFrozenBounds) {
-            bounds.writeToProto(proto, FROZEN_BOUNDS);
-        }
-        proto.end(token);
-    }
-
-    void writeNameToProto(ProtoOutputStream proto, long fieldId) {
-        if (appToken != null) {
-            proto.write(fieldId, appToken.getName());
-        }
-    }
-
-    void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
-        final long token = proto.start(fieldId);
-        proto.write(HASH_CODE, System.identityHashCode(this));
-        proto.write(USER_ID, mUserId);
-        proto.write(TITLE, ((ActivityRecord) this).intent.getComponent().flattenToShortString());
-        proto.end(token);
-    }
-
-    Rect getLetterboxInsets() {
-        if (mLetterbox != null) {
-            return mLetterbox.getInsets();
-        } else {
-            return new Rect();
-        }
-    }
-
-    /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
-    void getLetterboxInnerBounds(Rect outBounds) {
-        if (mLetterbox != null) {
-            outBounds.set(mLetterbox.getInnerFrame());
-        } else {
-            outBounds.setEmpty();
-        }
-    }
-
-    /**
-     * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
-     * the given {@code rect}.
-     */
-    boolean isLetterboxOverlappingWith(Rect rect) {
-        return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
-    }
-
-    /**
-     * Sets if this AWT is in the process of closing or entering PIP.
-     * {@link #mWillCloseOrEnterPip}}
-     */
-    void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
-        mWillCloseOrEnterPip = willCloseOrEnterPip;
-    }
-
-    /**
-     * Returns whether this AWT is considered closing. Conditions are either
-     * 1. Is this app animating and was requested to be hidden
-     * 2. App is delayed closing since it might enter PIP.
-     */
-    boolean isClosingOrEnteringPip() {
-        return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
-    }
-
-    /**
-     * @return Whether we are allowed to show non-starting windows at the moment. We disallow
-     *         showing windows during transitions in case we have windows that have wide-color-gamut
-     *         color mode set to avoid jank in the middle of the transition.
-     */
-    boolean canShowWindows() {
-        return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
-    }
-
-    /**
-     * @return true if we have a window that has a non-default color mode set; false otherwise.
-     */
-    private boolean hasNonDefaultColorWindow() {
-        return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
-                true /* topToBottom */);
-    }
-
-    private void updateColorTransform() {
-        if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
-            getPendingTransaction().setColorTransform(mSurfaceControl,
-                    mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
-            mWmService.scheduleAnimationLocked();
-        }
-    }
-
-    private static class AppSaturationInfo {
-        float[] mMatrix = new float[9];
-        float[] mTranslation = new float[3];
-
-        void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
-            System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
-            System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4c3611e..aa0b68b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -270,9 +270,9 @@
     final AppTransitionController mAppTransitionController;
     boolean mSkipAppTransitionAnimation = false;
 
-    final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
-    final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
-    final ArraySet<AppWindowToken> mChangingApps = new ArraySet<>();
+    final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>();
+    final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
+    final ArraySet<ActivityRecord> mChangingApps = new ArraySet<>();
     final UnknownAppVisibilityController mUnknownAppVisibilityController;
     BoundsAnimationController mBoundsAnimationController;
 
@@ -438,7 +438,7 @@
     /** A collection of windows that provide tap exclude regions inside of them. */
     final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
 
-    private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
+    private final LinkedList<ActivityRecord> mTmpUpdateAllDrawn = new LinkedList();
 
     private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
             new TaskForResizePointSearchResult();
@@ -480,7 +480,7 @@
      * the user taps on the area outside of the task of the focused app, we will notify AM about the
      * new task the user wants to interact with.
      */
-    AppWindowToken mFocusedApp = null;
+    ActivityRecord mFocusedApp = null;
 
     /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
     final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
@@ -563,9 +563,9 @@
 
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
         WindowStateAnimator winAnimator = w.mWinAnimator;
-        final AppWindowToken atoken = w.mAppToken;
+        final ActivityRecord activity = w.mActivityRecord;
         if (winAnimator.mDrawState == READY_TO_SHOW) {
-            if (atoken == null || atoken.canShowWindows()) {
+            if (activity == null || activity.canShowWindows()) {
                 if (w.performShowLocked()) {
                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
                     if (DEBUG_LAYOUT_REPEATS) {
@@ -589,7 +589,7 @@
     };
 
     private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
-        final AppWindowToken focusedApp = mFocusedApp;
+        final ActivityRecord focusedApp = mFocusedApp;
         ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b",
                 w, w.mAttrs.flags, w.canReceiveKeys());
 
@@ -597,12 +597,12 @@
             return false;
         }
 
-        final AppWindowToken wtoken = w.mAppToken;
+        final ActivityRecord activity = w.mActivityRecord;
 
         // If this window's application has been removed, just skip it.
-        if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
-            ProtoLog.v(WM_DEBUG_FOCUS, "Skipping %s because %s", wtoken,
-                    (wtoken.removed ? "removed" : "sendingToBottom"));
+        if (activity!= null && (activity.removed || activity.sendingToBottom)) {
+            ProtoLog.v(WM_DEBUG_FOCUS, "Skipping %s because %s", activity,
+                    (activity.removed ? "removed" : "sendingToBottom"));
             return false;
         }
 
@@ -622,9 +622,9 @@
         }
 
         // Descend through all of the app tokens and find the first that either matches
-        // win.mAppToken (return win) or mFocusedApp (return null).
-        if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
-            if (focusedApp.compareTo(wtoken) > 0) {
+        // win.mActivityRecord (return win) or mFocusedApp (return null).
+        if (activity != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
+            if (focusedApp.compareTo(activity) > 0) {
                 // App stack below focused app stack. No focus for you!!!
                 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
                         "findFocusedWindow: Reached focused app=%s", focusedApp);
@@ -648,14 +648,14 @@
             Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
                     + " mLayoutAttached=" + w.mLayoutAttached
                     + " config reported=" + w.isLastConfigReportedToClient());
-            final AppWindowToken atoken = w.mAppToken;
+            final ActivityRecord activity = w.mActivityRecord;
             if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
-                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+                    + " hiddenRequested=" + (activity != null && activity.hiddenRequested)
                     + " parentHidden=" + w.isParentWindowHidden());
             else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
                     + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.isHidden()
-                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
+                    + " hiddenRequested=" + (activity != null && activity.hiddenRequested)
                     + " parentHidden=" + w.isParentWindowHidden());
         }
 
@@ -683,8 +683,8 @@
                 w.updateLastInsetValues();
             }
 
-            if (w.mAppToken != null) {
-                w.mAppToken.layoutLetterbox(w);
+            if (w.mActivityRecord != null) {
+                w.mActivityRecord.layoutLetterbox(w);
             }
 
             if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.getFrameLw()
@@ -825,12 +825,12 @@
             }
         }
 
-        final AppWindowToken atoken = w.mAppToken;
-        if (atoken != null) {
-            atoken.updateLetterboxSurface(w);
-            final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
-            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
-                mTmpUpdateAllDrawn.add(atoken);
+        final ActivityRecord activity = w.mActivityRecord;
+        if (activity != null) {
+            activity.updateLetterboxSurface(w);
+            final boolean updateAllDrawn = activity.updateDrawnWindowStates(w);
+            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(activity)) {
+                mTmpUpdateAllDrawn.add(activity);
             }
         }
 
@@ -966,12 +966,12 @@
         return mTokenMap.get(binder);
     }
 
-    AppWindowToken getAppWindowToken(IBinder binder) {
+    ActivityRecord getActivityRecord(IBinder binder) {
         final WindowToken token = getWindowToken(binder);
         if (token == null) {
             return null;
         }
-        return token.asAppWindowToken();
+        return token.asActivityRecord();
     }
 
     private void addWindowToken(IBinder binder, WindowToken token) {
@@ -995,7 +995,7 @@
 
         mTokenMap.put(binder, token);
 
-        if (token.asAppWindowToken() == null) {
+        if (token.asActivityRecord() == null) {
             // Add non-app token to container hierarchy on the display. App tokens are added through
             // the parent container managing them (e.g. Tasks).
             switch (token.windowType) {
@@ -1015,7 +1015,7 @@
 
     WindowToken removeWindowToken(IBinder binder) {
         final WindowToken token = mTokenMap.remove(binder);
-        if (token != null && token.asAppWindowToken() == null) {
+        if (token != null && token.asActivityRecord() == null) {
             token.setExiting();
         }
         return token;
@@ -1028,7 +1028,7 @@
             return;
         }
         if (prevDc != null) {
-            if (prevDc.mTokenMap.remove(token.token) != null && token.asAppWindowToken() == null) {
+            if (prevDc.mTokenMap.remove(token.token) != null && token.asActivityRecord() == null) {
                 // Removed the token from the map, but made sure it's not an app token before
                 // removing from parent.
                 token.getParent().removeChild(token);
@@ -1057,14 +1057,14 @@
             return;
         }
 
-        final AppWindowToken appToken = token.asAppWindowToken();
+        final ActivityRecord activity = token.asActivityRecord();
 
-        if (appToken == null) {
+        if (activity == null) {
             Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
             return;
         }
 
-        appToken.onRemovedFromDisplay();
+        activity.onRemovedFromDisplay();
     }
 
     @Override
@@ -1255,9 +1255,9 @@
             // If we changed the orientation but mOrientationChangeComplete is already true,
             // we used seamless rotation, and we don't need to freeze the screen.
             if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) {
-                final AppWindowToken atoken = getAppWindowToken(freezeDisplayToken);
-                if (atoken != null) {
-                    atoken.startFreezingScreen();
+                final ActivityRecord activity = getActivityRecord(freezeDisplayToken);
+                if (activity != null) {
+                    activity.startFreezingScreen();
                 }
             }
             config = new Configuration();
@@ -2979,10 +2979,10 @@
     /**
      * Set the new focused app to this display.
      *
-     * @param newFocus the new focused AppWindowToken.
+     * @param newFocus the new focused {@link ActivityRecord}.
      * @return true if the focused app is changed.
      */
-    boolean setFocusedApp(AppWindowToken newFocus) {
+    boolean setFocusedApp(ActivityRecord newFocus) {
         if (newFocus != null) {
             final DisplayContent appDisplay = newFocus.getDisplayContent();
             if (appDisplay != this) {
@@ -3050,10 +3050,10 @@
                 wsa.destroySurface();
                 mWmService.mForceRemoves.add(w);
                 mTmpWindow = w;
-            } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) {
+            } else if (w.mActivityRecord != null && w.mActivityRecord.isClientHidden()) {
                 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
                         + w + " surface=" + wsa.mSurfaceController
-                        + " token=" + w.mAppToken);
+                        + " token=" + w.mActivityRecord);
                 ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE LEAK DESTROY: %s", w);
                 wsa.destroySurface();
                 mTmpWindow = w;
@@ -3122,9 +3122,9 @@
         // to be on top of it, but it is not -really- where input will go. So look down below
         // for a real window to target...
         if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
-            final AppWindowToken token = target.mAppToken;
-            if (token != null) {
-                final WindowState betterTarget = token.getImeTargetBelowWindow(target);
+            final ActivityRecord activity = target.mActivityRecord;
+            if (activity != null) {
+                final WindowState betterTarget = activity.getImeTargetBelowWindow(target);
                 if (betterTarget != null) {
                     target = betterTarget;
                 }
@@ -3158,15 +3158,15 @@
         }
 
         if (updateImeTarget) {
-            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
-            if (token != null) {
+            ActivityRecord activity = curTarget == null ? null : curTarget.mActivityRecord;
+            if (activity != null) {
 
                 // Now some fun for dealing with window animations that modify the Z order. We need
                 // to look at all windows below the current target that are in this app, finding the
                 // highest visible one in layering.
                 WindowState highestTarget = null;
-                if (token.isSelfAnimating()) {
-                    highestTarget = token.getHighestAnimLayerWindow(curTarget);
+                if (activity.isSelfAnimating()) {
+                    highestTarget = activity.getHighestAnimLayerWindow(curTarget);
                 }
 
                 if (highestTarget != null) {
@@ -3194,8 +3194,8 @@
      * Calling {@link #computeImeTarget(boolean)} to update the input method target window in
      * the candidate app window token if needed.
      */
-    void computeImeTargetIfNeeded(AppWindowToken candidate) {
-        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == candidate) {
+    void computeImeTargetIfNeeded(ActivityRecord candidate) {
+        if (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord == candidate) {
             computeImeTarget(true /* updateImeTarget */);
         }
     }
@@ -3233,12 +3233,12 @@
         // Attach it to app if the target is part of an app and such app is covering the entire
         // screen. If it's not covering the entire screen the IME might extend beyond the apps
         // bounds.
-        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null
+        if (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord != null
                 && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
                 // An activity with override bounds should be letterboxed inside its parent bounds,
                 // so it doesn't fill the screen.
-                && mInputMethodTarget.mAppToken.matchParentBounds()) {
-            return mInputMethodTarget.mAppToken.getSurfaceControl();
+                && mInputMethodTarget.mActivityRecord.matchParentBounds()) {
+            return mInputMethodTarget.mActivityRecord.getSurfaceControl();
         }
 
         // Otherwise, we just attach it to the display.
@@ -3341,7 +3341,7 @@
             boolean subtle) {
         final WindowManagerPolicy policy = mWmService.mPolicy;
         forAllWindows(w -> {
-            if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)
+            if (w.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(w)
                     && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
                 w.startAnimation(policy.createHiddenByKeyguardExit(
                         onWallpaper, goingToShade, subtle));
@@ -3450,6 +3450,14 @@
         return win != null;
     }
 
+    void hideTransientBars() {
+        // TODO(b/118118435): Remove this after migration
+        final int transientFlags = View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
+        statusBarVisibilityChanged(mLastStatusBarVisibility & ~transientFlags);
+
+        getInsetsPolicy().hideTransient();
+    }
+
     void statusBarVisibilityChanged(int visibility) {
         mLastStatusBarVisibility = visibility;
         visibility = getDisplayPolicy().adjustSystemUiVisibilityLw(visibility);
@@ -3601,10 +3609,10 @@
         }
 
         while (!mTmpUpdateAllDrawn.isEmpty()) {
-            final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
+            final ActivityRecord activity = mTmpUpdateAllDrawn.removeLast();
             // See if any windows have been drawn, so they (and others associated with them)
             // can now be shown.
-            atoken.updateAllDrawn();
+            activity.updateAllDrawn();
         }
     }
 
@@ -4175,15 +4183,15 @@
 
         private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
                 boolean traverseTopToBottom) {
-            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
+            // For legacy reasons we process the TaskStack.mExitingActivities first here before the
             // app tokens.
             // TODO: Investigate if we need to continue to do this or if we can just process them
             // in-order.
             if (traverseTopToBottom) {
                 for (int i = mChildren.size() - 1; i >= 0; --i) {
-                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                    for (int j = appTokens.size() - 1; j >= 0; --j) {
-                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
+                    final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                    for (int j = activities.size() - 1; j >= 0; --j) {
+                        if (activities.get(j).forAllWindowsUnchecked(callback,
                                 traverseTopToBottom)) {
                             return true;
                         }
@@ -4192,10 +4200,10 @@
             } else {
                 final int count = mChildren.size();
                 for (int i = 0; i < count; ++i) {
-                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                    final int appTokensCount = appTokens.size();
+                    final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                    final int appTokensCount = activities.size();
                     for (int j = 0; j < appTokensCount; j++) {
-                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
+                        if (activities.get(j).forAllWindowsUnchecked(callback,
                                 traverseTopToBottom)) {
                             return true;
                         }
@@ -4207,27 +4215,27 @@
 
         void setExitingTokensHasVisible(boolean hasVisible) {
             for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                for (int j = appTokens.size() - 1; j >= 0; --j) {
-                    appTokens.get(j).hasVisible = hasVisible;
+                final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                for (int j = activities.size() - 1; j >= 0; --j) {
+                    activities.get(j).hasVisible = hasVisible;
                 }
             }
         }
 
         void removeExistingAppTokensIfPossible() {
             for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
-                for (int j = appTokens.size() - 1; j >= 0; --j) {
-                    final AppWindowToken token = appTokens.get(j);
-                    if (!token.hasVisible && !mClosingApps.contains(token)
-                            && (!token.mIsExiting || token.isEmpty())) {
-                        // Make sure there is no animation running on this token, so any windows
+                final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                for (int j = activities.size() - 1; j >= 0; --j) {
+                    final ActivityRecord activity = activities.get(j);
+                    if (!activity.hasVisible && !mClosingApps.contains(activity)
+                            && (!activity.mIsExiting || activity.isEmpty())) {
+                        // Make sure there is no animation running on this activity, so any windows
                         // associated with it will be removed as soon as their animations are
                         // complete.
                         cancelAnimation();
                         ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                                "performLayout: App token exiting now removed %s", token);
-                        token.removeIfPossible();
+                                "performLayout: Activity exiting now removed %s", activity);
+                        activity.removeIfPossible();
                     }
                 }
             }
@@ -4642,7 +4650,7 @@
         // Keep IME window in mAboveAppWindowsContainers as long as app's starting window exists
         // so it get's layered above the starting window.
         if (imeTarget != null
-                && !(imeTarget.mAppToken != null && imeTarget.mAppToken.hasStartingWindow())
+                && !(imeTarget.mActivityRecord != null && imeTarget.mActivityRecord.hasStartingWindow())
                 && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
                 && (imeTarget.getSurfaceControl() != null))) {
             mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 60e9819..a783ee9 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -30,7 +30,11 @@
 import static android.view.InsetsState.TYPE_TOP_TAPPABLE_ELEMENT;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
@@ -129,6 +133,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.ArraySet;
+import android.util.IntArray;
 import android.util.Pair;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
@@ -145,6 +150,7 @@
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewRootImpl;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerGlobal;
@@ -158,6 +164,7 @@
 import com.android.internal.util.ScreenShapeHelper;
 import com.android.internal.util.ScreenshotHelper;
 import com.android.internal.util.function.TriConsumer;
+import com.android.internal.view.AppearanceRegion;
 import com.android.internal.widget.PointerLocationView;
 import com.android.server.LocalServices;
 import com.android.server.UiThread;
@@ -235,7 +242,7 @@
     @Px
     private int mSideGestureInset;
 
-    private StatusBarManagerInternal getStatusBarManagerInternal() {
+    StatusBarManagerInternal getStatusBarManagerInternal() {
         synchronized (mServiceAcquireLock) {
             if (mStatusBarManagerInternal == null) {
                 mStatusBarManagerInternal =
@@ -327,14 +334,18 @@
     private int mForceClearedSystemUiFlags = 0;
     private int mLastFullscreenStackSysUiFlags;
     private int mLastDockedStackSysUiFlags;
+    private int mLastAppearance;
+    private int mLastFullscreenAppearance;
+    private int mLastDockedAppearance;
     private final Rect mNonDockedStackBounds = new Rect();
     private final Rect mDockedStackBounds = new Rect();
     private final Rect mLastNonDockedStackBounds = new Rect();
     private final Rect mLastDockedStackBounds = new Rect();
 
-    // What we last reported to system UI about whether the compatibility
-    // menu needs to be displayed.
-    private boolean mLastFocusNeedsMenu = false;
+    // What we last reported to system UI about whether the focused window is fullscreen/immersive.
+    private boolean mLastFocusIsFullscreen = false;
+    private boolean mLastFocusIsImmersive = false;
+
     // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending.
     private long mPendingPanicGestureUptime;
 
@@ -865,6 +876,8 @@
                 if (canToastShowWhenLocked(callingPid)) {
                     attrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
                 }
+                // Toasts can't be clickable
+                attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
                 break;
         }
 
@@ -2535,7 +2548,6 @@
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
                     }
                 } else if (topIsFullscreen
-                        && !mDisplayContent.isStackVisible(WINDOWING_MODE_FREEFORM)
                         && !mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
                     if (mStatusBarController.setBarShowingLw(false)) {
@@ -2595,7 +2607,7 @@
      *         window.
      */
     private boolean topAppHidesStatusBar() {
-        if (mTopFullscreenOpaqueWindowState == null) {
+        if (mTopFullscreenOpaqueWindowState == null || mForceShowSystemBars) {
             return false;
         }
         final int fl = PolicyControl.getWindowFlags(null,
@@ -3045,19 +3057,38 @@
                 // Swipe-up for navigation bar is disabled during setup
                 return;
             }
-            boolean sb = mStatusBarController.checkShowTransientBarLw();
-            boolean nb = mNavigationBarController.checkShowTransientBarLw()
-                    && !isNavBarEmpty(mLastSystemUiFlags);
-            if (sb || nb) {
-                // Don't show status bar when swiping on already visible navigation bar
-                if (!nb && swipeTarget == mNavigationBar) {
-                    if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
+            if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
+                if (swipeTarget == mNavigationBar
+                        && !getInsetsPolicy().isHidden(InsetsState.TYPE_NAVIGATION_BAR)) {
+                    // Don't show status bar when swiping on already visible navigation bar
                     return;
                 }
-                if (sb) mStatusBarController.showTransient();
-                if (nb) mNavigationBarController.showTransient();
+                final InsetsControlTarget controlTarget =
+                        swipeTarget.getControllableInsetProvider().getControlTarget();
+                if (controlTarget == null) {
+                    return;
+                }
+                if (controlTarget.canShowTransient()) {
+                    mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
+                            new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+                } else {
+                    controlTarget.showInsets(WindowInsets.Type.systemBars(), false);
+                }
+            } else {
+                boolean sb = mStatusBarController.checkShowTransientBarLw();
+                boolean nb = mNavigationBarController.checkShowTransientBarLw()
+                        && !isNavBarEmpty(mLastSystemUiFlags);
+                if (sb || nb) {
+                    // Don't show status bar when swiping on already visible navigation bar
+                    if (!nb && swipeTarget == mNavigationBar) {
+                        if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
+                        return;
+                    }
+                    if (sb) mStatusBarController.showTransient();
+                    if (nb) mNavigationBarController.showTransient();
+                    updateSystemUiVisibilityLw();
+                }
                 mImmersiveModeConfirmation.confirmCurrentPrompt();
-                updateSystemUiVisibilityLw();
             }
         }
     }
@@ -3078,6 +3109,10 @@
         return mService.mPolicy.isKeyguardOccluded();
     }
 
+    InsetsPolicy getInsetsPolicy() {
+        return mDisplayContent.getInsetsPolicy();
+    }
+
     void resetSystemUiVisibilityLw() {
         mLastSystemUiFlags = 0;
         updateSystemUiVisibilityLw();
@@ -3129,14 +3164,20 @@
                     &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
         }
 
+        final int appearance = win.mAttrs.insetsFlags.appearance;
         final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
                 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
         final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
                 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
+        final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
+                mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
+        final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
+                mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
         mService.getStackBounds(
                 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
-        mService.getStackBounds(mDockedStackBounds.isEmpty()
-                        ? WINDOWING_MODE_FULLSCREEN : WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
+        final boolean inSplitScreen = !mDockedStackBounds.isEmpty();
+        mService.getStackBounds(inSplitScreen ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+                        : WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_UNDEFINED, mNonDockedStackBounds);
         final Pair<Integer, Boolean> result =
                 updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
@@ -3144,8 +3185,24 @@
         final int diff = visibility ^ mLastSystemUiFlags;
         final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
         final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
-        final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
-        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
+        final InsetsPolicy insetsPolicy = getInsetsPolicy();
+        final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
+                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
+                || (PolicyControl.getWindowFlags(win, win.mAttrs) & FLAG_FULLSCREEN) != 0
+                || (mStatusBar != null && insetsPolicy.isHidden(TYPE_TOP_BAR))
+                || (mNavigationBar != null && insetsPolicy.isHidden(
+                        InsetsState.TYPE_NAVIGATION_BAR));
+        final int behavior = win.mAttrs.insetsFlags.behavior;
+        final boolean isImmersive = (visibility & (View.SYSTEM_UI_FLAG_IMMERSIVE
+                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
+                || behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
+                || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+        if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0
+                && mLastAppearance == appearance
+                && mLastFullscreenAppearance == fullscreenAppearance
+                && mLastDockedAppearance == dockedAppearance
+                && mLastFocusIsFullscreen == isFullscreen
+                && mLastFocusIsImmersive == isImmersive
                 && mFocusedApp == win.getAppToken()
                 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
                 && mLastDockedStackBounds.equals(mDockedStackBounds)) {
@@ -3154,21 +3211,40 @@
         mLastSystemUiFlags = visibility;
         mLastFullscreenStackSysUiFlags = fullscreenVisibility;
         mLastDockedStackSysUiFlags = dockedVisibility;
-        mLastFocusNeedsMenu = needsMenu;
+        mLastAppearance = appearance;
+        mLastFullscreenAppearance = fullscreenAppearance;
+        mLastDockedAppearance = dockedAppearance;
+        mLastFocusIsFullscreen = isFullscreen;
+        mLastFocusIsImmersive = isImmersive;
         mFocusedApp = win.getAppToken();
         mLastNonDockedStackBounds.set(mNonDockedStackBounds);
         mLastDockedStackBounds.set(mDockedStackBounds);
         final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
         final Rect dockedStackBounds = new Rect(mDockedStackBounds);
+        final AppearanceRegion[] appearanceRegions = inSplitScreen
+                ? new AppearanceRegion[]{
+                        new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
+                        new AppearanceRegion(dockedAppearance, dockedStackBounds)}
+                : new AppearanceRegion[]{
+                        new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
         final boolean isNavbarColorManagedByIme = result.second;
         mHandler.post(() -> {
             StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
             if (statusBar != null) {
                 final int displayId = getDisplayId();
+                // TODO(b/118118435): disabled flags only
                 statusBar.setSystemUiVisibility(displayId, visibility, fullscreenVisibility,
                         dockedVisibility, 0xffffffff, fullscreenStackBounds,
                         dockedStackBounds, isNavbarColorManagedByIme, win.toString());
-                statusBar.topAppWindowChanged(displayId, needsMenu);
+                if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
+                    statusBar.onSystemBarAppearanceChanged(displayId, appearance,
+                            appearanceRegions, isNavbarColorManagedByIme);
+                }
+                statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
+
+                // TODO(b/118118435): Remove this after removing system UI visibilities.
+                mDisplayContent.statusBarVisibilityChanged(
+                        visibility & ~(View.STATUS_BAR_UNHIDE | View.NAVIGATION_BAR_UNHIDE));
             }
         });
         return diff;
@@ -3190,6 +3266,22 @@
         return vis;
     }
 
+    private int updateLightStatusBarAppearanceLw(int appearance, WindowState opaque,
+            WindowState opaqueOrDimming) {
+        final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
+        final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
+        if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
+            // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+            // its light flag.
+            appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
+            appearance |= statusColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_TOP_BAR;
+        } else if (statusColorWin != null && statusColorWin.isDimming()) {
+            // Otherwise if it's dimming, clear the light flag.
+            appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
+        }
+        return appearance;
+    }
+
     @VisibleForTesting
     @Nullable
     static WindowState chooseNavigationColorWindowLw(WindowState opaque,
@@ -3258,9 +3350,9 @@
         final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
 
         // We need to force system bars when the docked stack is visible, when the freeform stack
-        // is visible but also when we are resizing for the transitions when docked stack
+        // is focused but also when we are resizing for the transitions when docked stack
         // visibility changes.
-        mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing
+        mForceShowSystemBars = dockedStackVisible || win.inFreeformWindowingMode() || resizing
                 || mForceShowSystemBarsFromExternal;
         final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
 
@@ -3511,6 +3603,8 @@
                 mPendingPanicGestureUptime = SystemClock.uptimeMillis();
                 if (!isNavBarEmpty(mLastSystemUiFlags)) {
                     mNavigationBarController.showTransient();
+                    mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
+                            new int[] {InsetsState.TYPE_NAVIGATION_BAR}));
                 }
             }
         }
@@ -3588,9 +3682,6 @@
             pw.print(" mForceClearedSystemUiFlags=0x");
             pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
         }
-        if (mLastFocusNeedsMenu) {
-            pw.print(prefix); pw.print("mLastFocusNeedsMenu="); pw.println(mLastFocusNeedsMenu);
-        }
         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
         pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
         pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
@@ -3707,7 +3798,7 @@
     @VisibleForTesting
     static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) {
         if (navBarWindow == null || !navBarWindow.isVisibleLw()
-                || targetWindow.mAppToken == null || !targetWindow.isVisibleLw()) {
+                || targetWindow.mActivityRecord == null || !targetWindow.isVisibleLw()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 414e496..67f1d1b 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -520,7 +520,7 @@
 
         // If the bounds of activity window is different from its parent, then reject to be seamless
         // because the window position may change after rotation that will look like a sudden jump.
-        if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) {
+        if (w.mActivityRecord != null && !w.mActivityRecord.matchParentBounds()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index d3e42901..b454922 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -660,7 +660,7 @@
         checkMinimizeChanged(false /* animate */);
     }
 
-    void notifyAppTransitionStarting(ArraySet<AppWindowToken> openingApps, int appTransition) {
+    void notifyAppTransitionStarting(ArraySet<ActivityRecord> openingApps, int appTransition) {
         final boolean wasMinimized = mMinimizedDock;
         checkMinimizeChanged(true /* animate */);
 
@@ -685,10 +685,10 @@
     /**
      * @return true if {@param apps} contains an activity in the docked stack, false otherwise.
      */
-    private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
+    private boolean containsAppInDockedStack(ArraySet<ActivityRecord> apps) {
         for (int i = apps.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = apps.valueAt(i);
-            if (token.getTask() != null && token.inSplitScreenPrimaryWindowingMode()) {
+            final ActivityRecord activity = apps.valueAt(i);
+            if (activity.getTask() != null && activity.inSplitScreenPrimaryWindowingMode()) {
                 return true;
             }
         }
@@ -722,7 +722,7 @@
         final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
         final boolean minimizedForRecentsAnimation = recentsAnim != null &&
                 recentsAnim.isSplitScreenMinimized();
-        boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
+        boolean homeVisible = homeTask.getTopVisibleActivity() != null;
         if (homeVisible && topSecondaryStack != null) {
             // Home should only be considered visible if it is greater or equal to the top secondary
             // stack in terms of z-order.
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index abd7222..255ef6e 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -427,8 +427,8 @@
     private boolean targetWindowSupportsGlobalDrag(WindowState targetWin) {
         // Global drags are limited to system windows, and windows for apps that are targeting N and
         // above.
-        return targetWin.mAppToken == null
-                || targetWin.mAppToken.mTargetSdk >= Build.VERSION_CODES.N;
+        return targetWin.mActivityRecord == null
+                || targetWin.mActivityRecord.mTargetSdk >= Build.VERSION_CODES.N;
     }
 
     /* helper - send a ACTION_DRAG_STARTED event only if the window has not
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index bc95481..11f09d0 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -56,8 +56,6 @@
         if (mIsImeLayoutDrawn && mShowImeRunner != null) {
             // Show IME if InputMethodService requested to be shown and it's layout has finished.
             mShowImeRunner.run();
-            mIsImeLayoutDrawn = false;
-            mShowImeRunner = null;
         }
     }
 
@@ -74,10 +72,19 @@
                 mDisplayContent.mInputMethodTarget.showInsets(
                         WindowInsets.Type.ime(), true /* fromIme */);
             }
-            mImeTargetFromIme = null;
+            abortShowImePostLayout();
         };
     }
 
+    /**
+     * Abort any pending request to show IME post layout.
+     */
+    void abortShowImePostLayout() {
+        mImeTargetFromIme = null;
+        mIsImeLayoutDrawn = false;
+        mShowImeRunner = null;
+    }
+
     private boolean isImeTargetFromDisplayContentAndImeSame() {
         // IMMS#mLastImeTargetWindow always considers focused window as
         // IME target, however DisplayContent#computeImeTarget() can compute
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 9973e11..7f9e76b 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -81,7 +81,7 @@
      */
     @Override
     public long notifyANR(IBinder token, String reason) {
-        AppWindowToken appWindowToken = null;
+        ActivityRecord activity = null;
         WindowState windowState = null;
         boolean aboveSystem = false;
         //TODO(b/141764879) Limit scope of wm lock when input calls notifyANR
@@ -89,7 +89,7 @@
             if (token != null) {
                 windowState = mService.mInputToWindowMap.get(token);
                 if (windowState != null) {
-                    appWindowToken = windowState.mAppToken;
+                    activity = windowState.mActivityRecord;
                 }
             }
 
@@ -103,30 +103,30 @@
                 int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
                         TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
                 aboveSystem = windowState.mBaseLayer > systemAlertLayer;
-            } else if (appWindowToken != null) {
+            } else if (activity != null) {
                 Slog.i(TAG_WM, "Input event dispatching timed out "
-                        + "sending to application " + appWindowToken.stringName
+                        + "sending to application " + activity.stringName
                         + ".  Reason: " + reason);
             } else {
                 Slog.i(TAG_WM, "Input event dispatching timed out "
                         + ".  Reason: " + reason);
             }
 
-            mService.saveANRStateLocked(appWindowToken, windowState, reason);
+            mService.saveANRStateLocked(activity, windowState, reason);
         }
 
         // All the calls below need to happen without the WM lock held since they call into AM.
         mService.mAtmInternal.saveANRState(reason);
 
-        if (appWindowToken != null && appWindowToken.appToken != null) {
+        if (activity != null && activity.appToken != null) {
             // Notify the activity manager about the timeout and let it decide whether
             // to abort dispatching or keep waiting.
-            final boolean abort = appWindowToken.keyDispatchingTimedOut(reason,
+            final boolean abort = activity.keyDispatchingTimedOut(reason,
                     windowState.mSession.mPid);
             if (!abort) {
                 // The activity manager declined to abort dispatching.
                 // Wait a bit longer and timeout again later.
-                return appWindowToken.mInputDispatchingTimeoutNanos;
+                return activity.mInputDispatchingTimeoutNanos;
             }
         } else if (windowState != null) {
             // Notify the activity manager about the timeout and let it decide whether
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 584c6e1..f9ff2e3 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -263,7 +263,7 @@
         inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
         inputWindowHandle.hasFocus = hasFocus;
         inputWindowHandle.hasWallpaper = hasWallpaper;
-        inputWindowHandle.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+        inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
         inputWindowHandle.layer = child.mLayer;
         inputWindowHandle.ownerPid = child.mSession.mPid;
         inputWindowHandle.ownerUid = child.mSession.mUid;
@@ -353,7 +353,7 @@
         }
     }
 
-    public void setFocusedAppLw(AppWindowToken newApp) {
+    public void setFocusedAppLw(ActivityRecord newApp) {
         // Focused app has changed.
         if (newApp == null) {
             mService.mInputManager.setFocusedApplication(mDisplayId, null);
@@ -476,7 +476,7 @@
                 final RecentsAnimationController recentsAnimationController =
                         mService.getRecentsAnimationController();
                 if (recentsAnimationController != null
-                        && recentsAnimationController.shouldApplyInputConsumer(w.mAppToken)) {
+                        && recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord)) {
                     if (recentsAnimationController.updateInputConsumerForApp(
                             recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
                         recentsAnimationInputConsumer.show(mInputTransaction, w);
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 22ba82a..c8ce53d 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -42,4 +42,11 @@
      */
     default void hideInsets(@InsetType int types, boolean fromIme) {
     }
+
+    /**
+     * Returns {@code true} if the control target allows the system to show transient windows.
+     */
+    default boolean canShowTransient() {
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 2dc50d8..fc51b46 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -16,13 +16,22 @@
 
 package com.android.server.wm;
 
+import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
+import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
 
 import android.annotation.Nullable;
+import android.app.StatusBarManager;
+import android.util.IntArray;
+import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetType;
+import android.view.ViewRootImpl;
 
 /**
  * Policy that implements who gets control over the windows generating insets.
@@ -32,6 +41,12 @@
     private final InsetsStateController mStateController;
     private final DisplayContent mDisplayContent;
     private final DisplayPolicy mPolicy;
+    private final TransientControlTarget mTransientControlTarget = new TransientControlTarget();
+    private final IntArray mShowingTransientTypes = new IntArray();
+
+    private WindowState mFocusedWin;
+    private BarWindow mTopBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
+    private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
 
     InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) {
         mStateController = stateController;
@@ -41,11 +56,132 @@
 
     /** Updates the target which can control system bars. */
     void updateBarControlTarget(@Nullable WindowState focusedWin) {
+        mFocusedWin = focusedWin;
         mStateController.onBarControlTargetChanged(getTopControlTarget(focusedWin),
-                getNavControlTarget(focusedWin));
+                getFakeTopControlTarget(focusedWin),
+                getNavControlTarget(focusedWin),
+                getFakeNavControlTarget(focusedWin));
+        if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
+            return;
+        }
+        mTopBar.setVisible(focusedWin == null
+                || focusedWin != getTopControlTarget(focusedWin)
+                || focusedWin.getClientInsetsState().getSource(TYPE_TOP_BAR).isVisible());
+        mNavBar.setVisible(focusedWin == null
+                || focusedWin != getNavControlTarget(focusedWin)
+                || focusedWin.getClientInsetsState().getSource(TYPE_NAVIGATION_BAR).isVisible());
+    }
+
+    boolean isHidden(@InternalInsetType int type) {
+        final InsetsSourceProvider provider =  mStateController.peekSourceProvider(type);
+        return provider != null && provider.hasWindow() && !provider.getSource().isVisible();
+    }
+
+    void showTransient(IntArray types) {
+        boolean changed = false;
+        for (int i = types.size() - 1; i >= 0; i--) {
+            final int type = types.get(i);
+            if (mShowingTransientTypes.indexOf(type) != -1) {
+                continue;
+            }
+            if (!isHidden(type)) {
+                continue;
+            }
+            mShowingTransientTypes.add(type);
+            changed = true;
+        }
+        if (changed) {
+            updateBarControlTarget(mFocusedWin);
+            mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
+                    mShowingTransientTypes.toArray());
+            mStateController.notifyInsetsChanged();
+            // TODO(b/118118435): Animation
+        }
+    }
+
+    void hideTransient() {
+        if (mShowingTransientTypes.size() == 0) {
+            return;
+        }
+
+        // TODO(b/118118435): Animation
+        mShowingTransientTypes.clear();
+        updateBarControlTarget(mFocusedWin);
+        mStateController.notifyInsetsChanged();
+    }
+
+    /**
+     * @see InsetsStateController#getInsetsForDispatch
+     */
+    InsetsState getInsetsForDispatch(WindowState target) {
+        InsetsState state = mStateController.getInsetsForDispatch(target);
+        if (mShowingTransientTypes.size() == 0) {
+            return state;
+        }
+        for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+            state.setSourceVisible(mShowingTransientTypes.get(i), false);
+        }
+        return state;
+    }
+
+    void onInsetsModified(WindowState windowState, InsetsState state) {
+        mStateController.onInsetsModified(windowState, state);
+        checkAbortTransient(windowState, state);
+        if (ViewRootImpl.sNewInsetsMode != ViewRootImpl.NEW_INSETS_MODE_FULL) {
+            return;
+        }
+        if (windowState == getTopControlTarget(mFocusedWin)) {
+            mTopBar.setVisible(state.getSource(TYPE_TOP_BAR).isVisible());
+        }
+        if (windowState == getNavControlTarget(mFocusedWin)) {
+            mNavBar.setVisible(state.getSource(TYPE_NAVIGATION_BAR).isVisible());
+        }
+    }
+
+    /**
+     * Called when a window modified the insets state. If the window set a insets source to visible
+     * while it is shown transiently, we need to abort the transient state.
+     *
+     * @param windowState who changed the insets state.
+     * @param state the modified insets state.
+     */
+    private void checkAbortTransient(WindowState windowState, InsetsState state) {
+        if (mShowingTransientTypes.size() != 0) {
+            IntArray abortTypes = new IntArray();
+            for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+                final int type = mShowingTransientTypes.get(i);
+                if (mStateController.isFakeTarget(type, windowState)
+                        && state.getSource(type).isVisible()) {
+                    mShowingTransientTypes.remove(i);
+                    abortTypes.add(type);
+                }
+            }
+            if (abortTypes.size() > 0) {
+                mPolicy.getStatusBarManagerInternal().abortTransient(mDisplayContent.getDisplayId(),
+                        abortTypes.toArray());
+                updateBarControlTarget(mFocusedWin);
+            }
+        }
+    }
+
+    private @Nullable InsetsControlTarget getFakeTopControlTarget(@Nullable WindowState focused) {
+        if (mShowingTransientTypes.indexOf(TYPE_TOP_BAR) != -1) {
+            return focused;
+        }
+        return null;
+    }
+
+    private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) {
+        if (mShowingTransientTypes.indexOf(TYPE_NAVIGATION_BAR) != -1) {
+            return focused;
+        }
+        return null;
     }
 
     private @Nullable InsetsControlTarget getTopControlTarget(@Nullable WindowState focusedWin) {
+        if (mShowingTransientTypes.indexOf(TYPE_TOP_BAR) != -1) {
+            return mTransientControlTarget;
+        }
         if (areSystemBarsForciblyVisible() || isStatusBarForciblyVisible()) {
             return null;
         }
@@ -53,6 +189,9 @@
     }
 
     private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) {
+        if (mShowingTransientTypes.indexOf(TYPE_NAVIGATION_BAR) != -1) {
+            return mTransientControlTarget;
+        }
         if (areSystemBarsForciblyVisible() || isNavBarForciblyVisible()) {
             return null;
         }
@@ -66,7 +205,7 @@
         }
         final int privateFlags = statusBar.mAttrs.privateFlags;
 
-        // TODO: Pretend to the app that it's still able to control it?
+        // TODO(b/118118435): Pretend to the app that it's still able to control it?
         if ((privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
             return true;
         }
@@ -100,4 +239,31 @@
         return isDockedStackVisible || isFreeformStackVisible || isResizing;
     }
 
+    private class BarWindow {
+
+        private final int mId;
+        private  @StatusBarManager.WindowVisibleState int mState =
+                StatusBarManager.WINDOW_STATE_SHOWING;
+
+        BarWindow(int id) {
+            mId = id;
+        }
+
+        private void setVisible(boolean visible) {
+            final int state = visible ? WINDOW_STATE_SHOWING : WINDOW_STATE_HIDDEN;
+            if (mState != state) {
+                mState = state;
+                mPolicy.getStatusBarManagerInternal().setWindowState(
+                        mDisplayContent.getDisplayId(), mId, state);
+            }
+        }
+    }
+
+    // TODO(b/118118435): Implement animations for it (with SurfaceAnimator)
+    private class TransientControlTarget implements InsetsControlTarget {
+
+        @Override
+        public void notifyInsetsControlChanged() {
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 3731d3f..a7724a1 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -111,7 +111,9 @@
     void setWindow(@Nullable WindowState win,
             @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
         if (mWin != null) {
-            mWin.setInsetProvider(null);
+            if (mControllable) {
+                mWin.setControllableInsetProvider(null);
+            }
             // The window may be animating such that we can hand out the leash to the control
             // target. Revoke the leash by cancelling the animation to correct the state.
             // TODO: Ideally, we should wait for the animation to finish so previous window can
@@ -123,8 +125,8 @@
         if (win == null) {
             setServerVisible(false);
             mSource.setFrame(new Rect());
-        } else {
-            mWin.setInsetProvider(this);
+        } else if (mControllable) {
+            mWin.setControllableInsetProvider(this);
             if (mControlTarget != null) {
                 updateControlForTarget(mControlTarget, true /* force */);
             }
@@ -132,6 +134,13 @@
     }
 
     /**
+     * @return Whether there is a window which backs this source.
+     */
+    boolean hasWindow() {
+        return mWin != null;
+    }
+
+    /**
      * Called when a layout pass has occurred.
      */
     void onPostLayout() {
@@ -225,6 +234,10 @@
         return null;
     }
 
+    InsetsControlTarget getControlTarget() {
+        return mControlTarget;
+    }
+
     boolean isClientVisible() {
         return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
     }
@@ -241,9 +254,13 @@
         @Override
         public void startAnimation(SurfaceControl animationLeash, Transaction t,
                 OnAnimationFinishedCallback finishCallback) {
-            // TODO: use 0 alpha and remove t.hide() once b/138459974 is fixed.
-            t.setAlpha(animationLeash, 1 /* alpha */);
-            t.hide(animationLeash);
+            // TODO(b/118118435): We can remove the type check when implementing the transient bar
+            //                    animation.
+            if (mSource.getType() == TYPE_IME) {
+                // TODO: use 0 alpha and remove t.hide() once b/138459974 is fixed.
+                t.setAlpha(animationLeash, 1 /* alpha */);
+                t.hide(animationLeash);
+            }
 
             mCapturedLeash = animationLeash;
             final Rect frame = mWin.getWindowFrames().mFrame;
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index b0410335c..e055424 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.view.InsetsState.InternalInsetType;
 import static android.view.InsetsState.TYPE_IME;
 import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.TYPE_TOP_BAR;
@@ -31,6 +30,7 @@
 import android.view.InsetsSource;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetType;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -73,7 +73,7 @@
      * @return The state stripped of the necessary information.
      */
     InsetsState getInsetsForDispatch(WindowState target) {
-        final InsetsSourceProvider provider = target.getInsetProvider();
+        final InsetsSourceProvider provider = target.getControllableInsetProvider();
         if (provider == null) {
             return mState;
         }
@@ -123,6 +123,13 @@
     }
 
     /**
+     * @return The provider of a specific type or null if we don't have it.
+     */
+    @Nullable InsetsSourceProvider peekSourceProvider(@InternalInsetType int type) {
+        return mProviders.get(type);
+    }
+
+    /**
      * Called when a layout pass has occurred.
      */
     void onPostLayout() {
@@ -152,6 +159,10 @@
         }
     }
 
+    boolean isFakeTarget(@InternalInsetType int type, InsetsControlTarget target) {
+        return mTypeFakeControlTargetMap.get(type) == target;
+    }
+
     void onImeTargetChanged(@Nullable InsetsControlTarget imeTarget) {
         onControlChanged(TYPE_IME, imeTarget);
         notifyPendingInsetsControlChanged();
@@ -166,9 +177,13 @@
      *                       and visibility.
      */
     void onBarControlTargetChanged(@Nullable InsetsControlTarget topControlling,
-            @Nullable InsetsControlTarget navControlling) {
+            @Nullable InsetsControlTarget fakeTopControlling,
+            @Nullable InsetsControlTarget navControlling,
+            @Nullable InsetsControlTarget fakeNavControlling) {
         onControlChanged(TYPE_TOP_BAR, topControlling);
         onControlChanged(TYPE_NAVIGATION_BAR, navControlling);
+        onControlFakeTargetChanged(TYPE_TOP_BAR, fakeTopControlling);
+        onControlFakeTargetChanged(TYPE_NAVIGATION_BAR, fakeNavControlling);
         notifyPendingInsetsControlChanged();
     }
 
@@ -279,7 +294,7 @@
         });
     }
 
-    private void notifyInsetsChanged() {
+    void notifyInsetsChanged() {
         mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
     }
 
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index c59a73b..6721ef8 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -174,7 +174,7 @@
 
         InputInterceptor(String namePrefix, WindowState win) {
             mWmService = win.mWmService;
-            final String name = namePrefix + (win.mAppToken != null ? win.mAppToken : win);
+            final String name = namePrefix + (win.mActivityRecord != null ? win.mActivityRecord : win);
             final InputChannel[] channels = InputChannel.openInputChannelPair(name);
             mServerChannel = channels[0];
             mClientChannel = channels[1];
diff --git a/services/core/java/com/android/server/wm/ProtoLogGroup.java b/services/core/java/com/android/server/wm/ProtoLogGroup.java
index f5a1884..5c2830e 100644
--- a/services/core/java/com/android/server/wm/ProtoLogGroup.java
+++ b/services/core/java/com/android/server/wm/ProtoLogGroup.java
@@ -129,7 +129,7 @@
     private static class Consts {
         private static final String TAG_WM = "WindowManager";
 
-        private static final boolean ENABLE_DEBUG = false;
+        private static final boolean ENABLE_DEBUG = true;
         private static final boolean ENABLE_LOG_TO_PROTO_DEBUG = true;
     }
 }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 12579e6..b7d25c3 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -247,7 +247,7 @@
                     "startRecentsActivity");
             mWindowManager.initializeRecentsAnimation(mTargetActivityType, recentsAnimationRunner,
                     this, mDefaultDisplay.mDisplayId,
-                    mStackSupervisor.mRecentTasks.getRecentTaskIds());
+                    mStackSupervisor.mRecentTasks.getRecentTaskIds(), targetActivity);
 
             // If we updated the launch-behind state, update the visibility of the activities after
             // we fetch the visible tasks to be controlled by the animation
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index d606e5d..7a3e43b 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -104,7 +104,7 @@
             "failSafeRunnable");
 
     // The recents component app token that is shown behind the visibile tasks
-    private AppWindowToken mTargetAppToken;
+    private ActivityRecord mTargetActivityRecord;
     private DisplayContent mDisplayContent;
     private int mTargetActivityType;
     private Rect mMinimizedHomeBounds = new Rect();
@@ -358,7 +358,8 @@
      * because it may call cancelAnimation() which needs to properly clean up the controller
      * in the window manager.
      */
-    public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) {
+    public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds,
+            ActivityRecord targetActivity) {
         mTargetActivityType = targetActivityType;
         mDisplayContent.mAppTransition.registerListenerLocked(mAppTransitionListener);
 
@@ -400,16 +401,12 @@
         }
 
         // Adjust the wallpaper visibility for the showing target activity
-        final AppWindowToken recentsComponentAppToken =
-                targetStack.getTopChild().getTopFullscreenAppToken();
-        if (recentsComponentAppToken != null) {
-            ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
-                    "setHomeApp(%s)", recentsComponentAppToken.getName());
-            mTargetAppToken = recentsComponentAppToken;
-            if (recentsComponentAppToken.windowsCanBeWallpaperTarget()) {
-                mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-                mDisplayContent.setLayoutNeeded();
-            }
+        ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
+                "setHomeApp(%s)", targetActivity.getName());
+        mTargetActivityRecord = targetActivity;
+        if (targetActivity.windowsCanBeWallpaperTarget()) {
+            mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+            mDisplayContent.setLayoutNeeded();
         }
 
         // Save the minimized home height
@@ -480,13 +477,13 @@
             // insets for the target app window after a rotation
             mDisplayContent.performLayout(false /* initial */, false /* updateInputWindows */);
 
-            final Rect minimizedHomeBounds = mTargetAppToken != null
-                    && mTargetAppToken.inSplitScreenSecondaryWindowingMode()
+            final Rect minimizedHomeBounds = mTargetActivityRecord != null
+                    && mTargetActivityRecord.inSplitScreenSecondaryWindowingMode()
                             ? mMinimizedHomeBounds
                             : null;
             final Rect contentInsets;
-            if (mTargetAppToken != null && mTargetAppToken.findMainWindow() != null) {
-                contentInsets = mTargetAppToken.findMainWindow().getContentInsets();
+            if (mTargetActivityRecord != null && mTargetActivityRecord.findMainWindow() != null) {
+                contentInsets = mTargetActivityRecord.findMainWindow().getContentInsets();
             } else {
                 // If the window for the activity had not yet been created, use the display insets.
                 mService.getStableInsets(mDisplayId, mTmpRect);
@@ -682,10 +679,10 @@
 
         // We have deferred all notifications to the target app as a part of the recents animation,
         // so if we are actually transitioning there, notify again here
-        if (mTargetAppToken != null) {
+        if (mTargetActivityRecord != null) {
             if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
                 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
-                        mTargetAppToken.token);
+                        mTargetActivityRecord.token);
             }
         }
 
@@ -740,25 +737,26 @@
     }
 
     boolean isWallpaperVisible(WindowState w) {
-        return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION && w.mAppToken != null
-                && mTargetAppToken == w.mAppToken && isTargetOverWallpaper();
+        return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION && w.mActivityRecord != null
+                && mTargetActivityRecord == w.mActivityRecord && isTargetOverWallpaper();
     }
 
     /**
      * @return Whether to use the input consumer to override app input to route home/recents.
      */
-    boolean shouldApplyInputConsumer(AppWindowToken appToken) {
+    boolean shouldApplyInputConsumer(ActivityRecord activity) {
         // Only apply the input consumer if it is enabled, it is not the target (home/recents)
         // being revealed with the transition, and we are actively animating the app as a part of
         // the animation
-        return mInputConsumerEnabled && mTargetAppToken != appToken && isAnimatingApp(appToken);
+        return mInputConsumerEnabled && mTargetActivityRecord != activity
+                && isAnimatingApp(activity);
     }
 
     boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
             boolean hasFocus) {
         // Update the input consumer touchable region to match the target app main window
-        final WindowState targetAppMainWindow = mTargetAppToken != null
-                ? mTargetAppToken.findMainWindow()
+        final WindowState targetAppMainWindow = mTargetActivityRecord != null
+                ? mTargetActivityRecord.findMainWindow()
                 : null;
         if (targetAppMainWindow != null) {
             targetAppMainWindow.getBounds(mTmpRect);
@@ -769,15 +767,15 @@
         return false;
     }
 
-    boolean isTargetApp(AppWindowToken token) {
-        return mTargetAppToken != null && token == mTargetAppToken;
+    boolean isTargetApp(ActivityRecord activity) {
+        return mTargetActivityRecord != null && activity == mTargetActivityRecord;
     }
 
     private boolean isTargetOverWallpaper() {
-        if (mTargetAppToken == null) {
+        if (mTargetActivityRecord == null) {
             return false;
         }
-        return mTargetAppToken.windowsCanBeWallpaperTarget();
+        return mTargetActivityRecord.windowsCanBeWallpaperTarget();
     }
 
     boolean isAnimatingTask(Task task) {
@@ -798,12 +796,12 @@
         return false;
     }
 
-    private boolean isAnimatingApp(AppWindowToken appToken) {
+    private boolean isAnimatingApp(ActivityRecord activity) {
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
             final Task task = mPendingAnimations.get(i).mTask;
             for (int j = task.getChildCount() - 1; j >= 0; j--) {
-                final AppWindowToken app = task.getChildAt(j);
-                if (app == appToken) {
+                final ActivityRecord app = task.getChildAt(j);
+                if (app == activity) {
                     return true;
                 }
             }
@@ -813,7 +811,7 @@
 
     boolean shouldIgnoreForAccessibility(WindowState windowState) {
         final Task task = windowState.getTask();
-        return task != null && isAnimatingTask(task) && !isTargetApp(windowState.mAppToken);
+        return task != null && isAnimatingTask(task) && !isTargetApp(windowState.mActivityRecord);
     }
 
     @VisibleForTesting
@@ -836,7 +834,7 @@
         }
 
         RemoteAnimationTarget createRemoteAnimationTarget() {
-            final AppWindowToken topApp = mTask.getTopVisibleAppToken();
+            final ActivityRecord topApp = mTask.getTopVisibleActivity();
             final WindowState mainWindow = topApp != null
                     ? topApp.findMainWindow()
                     : null;
@@ -845,7 +843,7 @@
             }
             final Rect insets = new Rect();
             mainWindow.getContentInsets(insets);
-            InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
+            InsetUtils.addInsets(insets, mainWindow.mActivityRecord.getLetterboxInsets());
             final int mode = topApp.getActivityType() == mTargetActivityType
                     ? MODE_OPENING
                     : MODE_CLOSING;
@@ -923,7 +921,7 @@
         pw.print(innerPrefix); pw.println("mCanceled=" + mCanceled);
         pw.print(innerPrefix); pw.println("mInputConsumerEnabled=" + mInputConsumerEnabled);
         pw.print(innerPrefix); pw.println("mSplitScreenMinimized=" + mSplitScreenMinimized);
-        pw.print(innerPrefix); pw.println("mTargetAppToken=" + mTargetAppToken);
+        pw.print(innerPrefix); pw.println("mTargetActivityRecord=" + mTargetActivityRecord);
         pw.print(innerPrefix); pw.println("isTargetOverWallpaper=" + isTargetOverWallpaper());
         pw.print(innerPrefix); pw.println("mRequestDeferCancelUntilNextTransition="
                 + mRequestDeferCancelUntilNextTransition);
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 2b2ae92..c23ffd9 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -76,20 +76,20 @@
     }
 
     /**
-     * Creates an animation record for each individual {@link AppWindowToken}.
+     * Creates an animation record for each individual {@link ActivityRecord}.
      *
-     * @param appWindowToken The app to animate.
+     * @param activity The app to animate.
      * @param position The position app bounds, in screen coordinates.
      * @param stackBounds The stack bounds of the app relative to position.
      * @param startBounds The stack bounds before the transition, in screen coordinates
      * @return The record representing animation(s) to run on the app.
      */
-    RemoteAnimationRecord createRemoteAnimationRecord(AppWindowToken appWindowToken,
-            Point position, Rect stackBounds, Rect startBounds) {
+    RemoteAnimationRecord createRemoteAnimationRecord(ActivityRecord activity, Point position,
+            Rect stackBounds, Rect startBounds) {
         ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): token=%s",
-                appWindowToken);
+                activity);
         final RemoteAnimationRecord adapters =
-                new RemoteAnimationRecord(appWindowToken, position, stackBounds, startBounds);
+                new RemoteAnimationRecord(activity, position, stackBounds, startBounds);
         mPendingAnimations.add(adapters);
         return adapters;
     }
@@ -169,11 +169,11 @@
             final RemoteAnimationRecord wrappers = mPendingAnimations.get(i);
             final RemoteAnimationTarget target = wrappers.createRemoteAnimationTarget();
             if (target != null) {
-                ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd token=%s", wrappers.mAppWindowToken);
+                ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd token=%s", wrappers.mActivityRecord);
                 targets.add(target);
             } else {
                 ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tRemove token=%s",
-                        wrappers.mAppWindowToken);
+                        wrappers.mActivityRecord);
 
                 // We can't really start an animation but we still need to make sure to finish the
                 // pending animation that was started by SurfaceAnimator
@@ -228,7 +228,7 @@
                                 .onAnimationFinished(adapters.mThumbnailAdapter);
                     }
                     mPendingAnimations.remove(i);
-                    ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tapp=%s", adapters.mAppWindowToken);
+                    ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tapp=%s", adapters.mActivityRecord);
                 }
 
                 for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) {
@@ -345,12 +345,12 @@
         RemoteAnimationAdapterWrapper mAdapter;
         RemoteAnimationAdapterWrapper mThumbnailAdapter = null;
         RemoteAnimationTarget mTarget;
-        final AppWindowToken mAppWindowToken;
+        final ActivityRecord mActivityRecord;
         final Rect mStartBounds;
 
-        RemoteAnimationRecord(AppWindowToken appWindowToken, Point endPos, Rect endBounds,
+        RemoteAnimationRecord(ActivityRecord activityRecord, Point endPos, Rect endBounds,
                 Rect startBounds) {
-            mAppWindowToken = appWindowToken;
+            mActivityRecord = activityRecord;
             mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, endBounds);
             if (startBounds != null) {
                 mStartBounds = new Rect(startBounds);
@@ -366,8 +366,8 @@
         }
 
         RemoteAnimationTarget createRemoteAnimationTarget() {
-            final Task task = mAppWindowToken.getTask();
-            final WindowState mainWindow = mAppWindowToken.findMainWindow();
+            final Task task = mActivityRecord.getTask();
+            final WindowState mainWindow = mActivityRecord.findMainWindow();
             if (task == null || mainWindow == null || mAdapter == null
                     || mAdapter.mCapturedFinishCallback == null
                     || mAdapter.mCapturedLeash == null) {
@@ -375,11 +375,11 @@
             }
             final Rect insets = new Rect();
             mainWindow.getContentInsets(insets);
-            InsetUtils.addInsets(insets, mAppWindowToken.getLetterboxInsets());
+            InsetUtils.addInsets(insets, mActivityRecord.getLetterboxInsets());
             mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
-                    mAdapter.mCapturedLeash, !mAppWindowToken.fillsParent(),
+                    mAdapter.mCapturedLeash, !mActivityRecord.fillsParent(),
                     mainWindow.mWinAnimator.mLastClipRect, insets,
-                    mAppWindowToken.getPrefixOrderIndex(), mAdapter.mPosition,
+                    mActivityRecord.getPrefixOrderIndex(), mAdapter.mPosition,
                     mAdapter.mStackBounds, task.getWindowConfiguration(), false /*isNotInRecents*/,
                     mThumbnailAdapter != null ? mThumbnailAdapter.mCapturedLeash : null,
                     mStartBounds);
@@ -387,10 +387,10 @@
         }
 
         private int getMode() {
-            final DisplayContent dc = mAppWindowToken.getDisplayContent();
-            if (dc.mOpeningApps.contains(mAppWindowToken)) {
+            final DisplayContent dc = mActivityRecord.getDisplayContent();
+            if (dc.mOpeningApps.contains(mActivityRecord)) {
                 return RemoteAnimationTarget.MODE_OPENING;
-            } else if (dc.mChangingApps.contains(mAppWindowToken)) {
+            } else if (dc.mChangingApps.contains(mActivityRecord)) {
                 return RemoteAnimationTarget.MODE_CHANGING;
             } else {
                 return RemoteAnimationTarget.MODE_CLOSING;
@@ -423,7 +423,7 @@
             ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
 
             // Restore z-layering, position and stack crop until client has a chance to modify it.
-            t.setLayer(animationLeash, mRecord.mAppWindowToken.getPrefixOrderIndex());
+            t.setLayer(animationLeash, mRecord.mActivityRecord.getPrefixOrderIndex());
             if (mRecord.mStartBounds != null) {
                 t.setPosition(animationLeash, mRecord.mStartBounds.left, mRecord.mStartBounds.top);
                 t.setWindowCrop(animationLeash, mRecord.mStartBounds.width(),
@@ -464,7 +464,7 @@
 
         @Override
         public void dump(PrintWriter pw, String prefix) {
-            pw.print(prefix); pw.print("token="); pw.println(mRecord.mAppWindowToken);
+            pw.print(prefix); pw.print("token="); pw.println(mRecord.mActivityRecord);
             if (mRecord.mTarget != null) {
                 pw.print(prefix); pw.println("Target:");
                 mRecord.mTarget.dump(pw, prefix + "  ");
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 60833c3..9db6dc2 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1780,8 +1780,12 @@
         // If {@code r} is already in target display and its task is the same as the candidate task,
         // the intention should be getting a launch stack for the reusable activity, so we can use
         // the existing stack.
-        if (r.getDisplayId() == displayId && r.getTaskRecord() == candidateTask) {
-            return candidateTask.getStack();
+        if (candidateTask != null
+                && (r.getTaskRecord() == null || r.getTaskRecord() == candidateTask)) {
+            final int attachedDisplayId = r.getDisplayId();
+            if (attachedDisplayId == INVALID_DISPLAY || attachedDisplayId == displayId) {
+                return candidateTask.getStack();
+            }
         }
 
         int windowingMode;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b6a05d1..17f5abd 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -129,7 +129,7 @@
     private int mTopFocusedDisplayId = INVALID_DISPLAY;
 
     // Map from the PID to the top most app which has a focused window of the process.
-    final HashMap<Integer, AppWindowToken> mTopFocusedAppByProcess = new HashMap<>();
+    final HashMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new HashMap<>();
 
     // Only a separate transaction until we separate the apply surface changes
     // transaction from the global transaction.
@@ -145,9 +145,9 @@
     };
 
     private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
-        final AppWindowToken aToken = w.mAppToken;
-        if (aToken != null) {
-            aToken.removeReplacedWindowIfNeeded(w);
+        final ActivityRecord activity = w.mActivityRecord;
+        if (activity != null) {
+            activity.removeReplacedWindowIfNeeded(w);
         }
     };
 
@@ -175,7 +175,7 @@
             if (newFocus != null) {
                 final int pidOfNewFocus = newFocus.mSession.mPid;
                 if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) {
-                    mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mAppToken);
+                    mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord);
                 }
                 if (topFocusedDisplayId == INVALID_DISPLAY) {
                     topFocusedDisplayId = dc.getDisplayId();
@@ -330,12 +330,12 @@
      * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
      * AppWindowToken represents an activity which can only exist on one display.
      */
-    AppWindowToken getAppWindowToken(IBinder binder) {
+    ActivityRecord getActivityRecord(IBinder binder) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final DisplayContent dc = mChildren.get(i);
-            final AppWindowToken atoken = dc.getAppWindowToken(binder);
-            if (atoken != null) {
-                return atoken;
+            final ActivityRecord activity = dc.getActivityRecord(binder);
+            if (activity != null) {
+                return activity;
             }
         }
         return null;
@@ -541,8 +541,8 @@
                     ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
                             "SURFACE RECOVER DESTROY: %s",  winAnimator.mWin);
                     winAnimator.destroySurface();
-                    if (winAnimator.mWin.mAppToken != null) {
-                        winAnimator.mWin.mAppToken.removeStartingWindow();
+                    if (winAnimator.mWin.mActivityRecord != null) {
+                        winAnimator.mWin.mActivityRecord.removeStartingWindow();
                     }
                 }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index b047d8f..06e7d66 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -465,7 +465,8 @@
             final WindowState windowState = mService.windowForClientLocked(this, window,
                     false /* throwOnError */);
             if (windowState != null) {
-                windowState.getDisplayContent().getInsetsStateController().onInsetsModified(
+                windowState.setClientInsetsState(state);
+                windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(
                         windowState, state);
             }
         }
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index c9e43c5..3764122 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -35,7 +35,7 @@
     }
 
     @Override
-    StartingSurface createStartingSurface(AppWindowToken atoken) {
-        return mService.mTaskSnapshotController.createStartingSurface(atoken, mSnapshot);
+    StartingSurface createStartingSurface(ActivityRecord activity) {
+        return mService.mTaskSnapshotController.createStartingSurface(activity, mSnapshot);
     }
 }
diff --git a/services/core/java/com/android/server/wm/SplashScreenStartingData.java b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
index f52ce38..726b7da 100644
--- a/services/core/java/com/android/server/wm/SplashScreenStartingData.java
+++ b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
@@ -52,9 +52,9 @@
     }
 
     @Override
-    StartingSurface createStartingSurface(AppWindowToken atoken) {
-        return mService.mPolicy.addSplashScreen(atoken.token, mPkg, mTheme, mCompatInfo,
+    StartingSurface createStartingSurface(ActivityRecord activity) {
+        return mService.mPolicy.addSplashScreen(activity.token, mPkg, mTheme, mCompatInfo,
                 mNonLocalizedLabel, mLabelRes, mIcon, mLogo, mWindowFlags,
-                mMergedOverrideConfiguration, atoken.getDisplayContent().getDisplayId());
+                mMergedOverrideConfiguration, activity.getDisplayContent().getDisplayId());
     }
 }
diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
index eb5011f..2e6e777 100644
--- a/services/core/java/com/android/server/wm/StartingData.java
+++ b/services/core/java/com/android/server/wm/StartingData.java
@@ -33,9 +33,9 @@
      * Creates the actual starting window surface. DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING
      * THIS METHOD.
      *
-     * @param atoken the app to add the starting window to
+     * @param activity the app to add the starting window to
      * @return a class implementing {@link StartingSurface} for easy removal with
      *         {@link StartingSurface#remove}
      */
-    abstract StartingSurface createStartingSurface(AppWindowToken atoken);
-}
\ No newline at end of file
+    abstract StartingSurface createStartingSurface(ActivityRecord activity);
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 2657826..1db3149f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -291,7 +291,7 @@
         super.removeChild(child);
 
         if (mChildren.isEmpty()) {
-            EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeAppToken: last token");
+            EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeActivity: last activity");
             if (mDeferRemoval) {
                 removeIfPossible();
             }
@@ -413,7 +413,7 @@
 
     /**
      * Prepares the task bounds to be frozen with the current size. See
-     * {@link AppWindowToken#freezeBounds}.
+     * {@link ActivityRecord#freezeBounds}.
      */
     void prepareFreezingBounds() {
         mPreparedFrozenBounds.set(getBounds());
@@ -474,7 +474,7 @@
     private boolean getMaxVisibleBounds(Rect out) {
         boolean foundTop = false;
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mChildren.get(i);
+            final ActivityRecord token = mChildren.get(i);
             // skip hidden (or about to hide) apps
             if (token.mIsExiting || token.isClientHidden() || token.hiddenRequested) {
                 continue;
@@ -651,24 +651,24 @@
     }
 
     WindowState getTopVisibleAppMainWindow() {
-        final AppWindowToken token = getTopVisibleAppToken();
-        return token != null ? token.findMainWindow() : null;
+        final ActivityRecord activity = getTopVisibleActivity();
+        return activity != null ? activity.findMainWindow() : null;
     }
 
-    AppWindowToken getTopFullscreenAppToken() {
+    ActivityRecord getTopFullscreenActivity() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mChildren.get(i);
-            final WindowState win = token.findMainWindow();
+            final ActivityRecord activity = mChildren.get(i);
+            final WindowState win = activity.findMainWindow();
             if (win != null && win.mAttrs.isFullscreen()) {
-                return token;
+                return activity;
             }
         }
         return null;
     }
 
-    AppWindowToken getTopVisibleAppToken() {
+    ActivityRecord getTopVisibleActivity() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken token = mChildren.get(i);
+            final ActivityRecord token = mChildren.get(i);
             // skip hidden (or about to hide) apps
             if (!token.mIsExiting && !token.isClientHidden() && !token.hiddenRequested) {
                 return token;
@@ -786,8 +786,8 @@
         super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
         proto.write(ID, mTaskId);
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken appWindowToken = mChildren.get(i);
-            appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, logLevel);
+            final ActivityRecord activity = mChildren.get(i);
+            activity.writeToProto(proto, APP_WINDOW_TOKENS, logLevel);
         }
         proto.write(FILLS_PARENT, matchParentBounds());
         getBounds().writeToProto(proto, BOUNDS);
@@ -813,9 +813,9 @@
         final String quadruplePrefix = triplePrefix + "  ";
 
         for (int i = mChildren.size() - 1; i >= 0; i--) {
-            final AppWindowToken wtoken = mChildren.get(i);
-            pw.println(triplePrefix + "Activity #" + i + " " + wtoken);
-            wtoken.dump(pw, quadruplePrefix, dumpAll);
+            final ActivityRecord activity = mChildren.get(i);
+            pw.println(triplePrefix + "Activity #" + i + " " + activity);
+            activity.dump(pw, quadruplePrefix, dumpAll);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 56b3bba..ed07f30 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -172,7 +172,7 @@
         // on top (eg. a dialog window).
         WindowState transferFocusFromWin = win;
         if (displayContent.mCurrentFocus != null && displayContent.mCurrentFocus != win
-                && displayContent.mCurrentFocus.mAppToken == win.mAppToken) {
+                && displayContent.mCurrentFocus.mActivityRecord == win.mActivityRecord) {
             transferFocusFromWin = displayContent.mCurrentFocus;
         }
         if (!mInputManager.transferTouchFocus(
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index 8175c4a..9e55113 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -34,7 +34,7 @@
 
     private final WindowManagerService mService;
     private final TaskSnapshotLoader mLoader;
-    private final ArrayMap<AppWindowToken, Integer> mAppTaskMap = new ArrayMap<>();
+    private final ArrayMap<ActivityRecord, Integer> mAppTaskMap = new ArrayMap<>();
     private final ArrayMap<Integer, CacheEntry> mRunningCache = new ArrayMap<>();
 
     TaskSnapshotCache(WindowManagerService service, TaskSnapshotLoader loader) {
@@ -47,7 +47,7 @@
         if (entry != null) {
             mAppTaskMap.remove(entry.topApp);
         }
-        final AppWindowToken top = task.getTopChild();
+        final ActivityRecord top = task.getTopChild();
         mAppTaskMap.put(top, task.mTaskId);
         mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, task.getTopChild()));
     }
@@ -87,8 +87,8 @@
     /**
      * Called when an app token has been removed
      */
-    void onAppRemoved(AppWindowToken wtoken) {
-        final Integer taskId = mAppTaskMap.get(wtoken);
+    void onAppRemoved(ActivityRecord activity) {
+        final Integer taskId = mAppTaskMap.get(activity);
         if (taskId != null) {
             removeRunningEntry(taskId);
         }
@@ -97,8 +97,8 @@
     /**
      * Callend when an app window token's process died.
      */
-    void onAppDied(AppWindowToken wtoken) {
-        final Integer taskId = mAppTaskMap.get(wtoken);
+    void onAppDied(ActivityRecord activity) {
+        final Integer taskId = mAppTaskMap.get(activity);
         if (taskId != null) {
             removeRunningEntry(taskId);
         }
@@ -134,9 +134,9 @@
         final TaskSnapshot snapshot;
 
         /** The app token that was on top of the task when the snapshot was taken */
-        final AppWindowToken topApp;
+        final ActivityRecord topApp;
 
-        CacheEntry(TaskSnapshot snapshot, AppWindowToken topApp) {
+        CacheEntry(TaskSnapshot snapshot, ActivityRecord topApp) {
             this.snapshot = snapshot;
             this.topApp = topApp;
         }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index f9a6fe7..0d4ec65 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -140,13 +140,13 @@
     /**
      * Called when the visibility of an app changes outside of the regular app transition flow.
      */
-    void notifyAppVisibilityChanged(AppWindowToken appWindowToken, boolean visible) {
+    void notifyAppVisibilityChanged(ActivityRecord appWindowToken, boolean visible) {
         if (!visible) {
             handleClosingApps(Sets.newArraySet(appWindowToken));
         }
     }
 
-    private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
+    private void handleClosingApps(ArraySet<ActivityRecord> closingApps) {
         if (shouldDisableSnapshots()) {
             return;
         }
@@ -215,9 +215,9 @@
      * Creates a starting surface for {@param token} with {@param snapshot}. DO NOT HOLD THE WINDOW
      * MANAGER LOCK WHEN CALLING THIS METHOD!
      */
-    StartingSurface createStartingSurface(AppWindowToken token,
+    StartingSurface createStartingSurface(ActivityRecord activity,
             TaskSnapshot snapshot) {
-        return TaskSnapshotSurface.create(mService, token, snapshot);
+        return TaskSnapshotSurface.create(mService, activity, snapshot);
     }
 
     /**
@@ -225,21 +225,21 @@
      * we're looking for, but during app transitions, trampoline activities can appear in the
      * children, which should be ignored.
      */
-    @Nullable private AppWindowToken findAppTokenForSnapshot(Task task) {
+    @Nullable private ActivityRecord findAppTokenForSnapshot(Task task) {
         for (int i = task.getChildCount() - 1; i >= 0; --i) {
-            final AppWindowToken appWindowToken = task.getChildAt(i);
-            if (appWindowToken == null || !appWindowToken.isSurfaceShowing()
-                    || appWindowToken.findMainWindow() == null) {
+            final ActivityRecord activity = task.getChildAt(i);
+            if (activity == null || !activity.isSurfaceShowing()
+                    || activity.findMainWindow() == null) {
                 continue;
             }
-            final boolean hasVisibleChild = appWindowToken.forAllWindows(
+            final boolean hasVisibleChild = activity.forAllWindows(
                     // Ensure at least one window for the top app is visible before attempting to
                     // take a screenshot. Visible here means that the WSA surface is shown and has
                     // an alpha greater than 0.
                     ws -> ws.mWinAnimator != null && ws.mWinAnimator.getShown()
                             && ws.mWinAnimator.mLastAlpha > 0f, true  /* traverseTopToBottom */);
             if (hasVisibleChild) {
-                return appWindowToken;
+                return activity;
             }
         }
         return null;
@@ -275,16 +275,16 @@
             return null;
         }
 
-        final AppWindowToken appWindowToken = findAppTokenForSnapshot(task);
-        if (appWindowToken == null) {
+        final ActivityRecord activity = findAppTokenForSnapshot(task);
+        if (activity == null) {
             if (DEBUG_SCREENSHOT) {
                 Slog.w(TAG_WM, "Failed to take screenshot. No visible windows for " + task);
             }
             return null;
         }
-        if (appWindowToken.hasCommittedReparentToAnimationLeash()) {
+        if (activity.hasCommittedReparentToAnimationLeash()) {
             if (DEBUG_SCREENSHOT) {
-                Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + appWindowToken);
+                Slog.w(TAG_WM, "Failed to take screenshot. App is animating " + activity);
             }
             return null;
         }
@@ -294,7 +294,7 @@
                 ? mPersister.getReducedScale()
                 : mFullSnapshotScale;
 
-        final WindowState mainWindow = appWindowToken.findMainWindow();
+        final WindowState mainWindow = activity.findMainWindow();
         if (mainWindow == null) {
             Slog.w(TAG_WM, "Failed to take screenshot. No main window for " + task);
             return null;
@@ -311,12 +311,12 @@
         final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
         return new TaskSnapshot(
                 System.currentTimeMillis() /* id */,
-                appWindowToken.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
+                activity.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
                 screenshotBuffer.getColorSpace(),
-                appWindowToken.getTask().getConfiguration().orientation,
+                activity.getTask().getConfiguration().orientation,
                 getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
                 true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
-                !appWindowToken.fillsParent() || isWindowTranslucent);
+                !activity.fillsParent() || isWindowTranslucent);
     }
 
     private boolean shouldDisableSnapshots() {
@@ -327,7 +327,7 @@
         // XXX(b/72757033): These are insets relative to the window frame, but we're really
         // interested in the insets relative to the task bounds.
         final Rect insets = minRect(state.getContentInsets(), state.getStableInsets());
-        InsetUtils.addInsets(insets, state.mAppToken.getLetterboxInsets());
+        InsetUtils.addInsets(insets, state.mActivityRecord.getLetterboxInsets());
         return insets;
     }
 
@@ -342,11 +342,11 @@
      * Retrieves all closing tasks based on the list of closing apps during an app transition.
      */
     @VisibleForTesting
-    void getClosingTasks(ArraySet<AppWindowToken> closingApps, ArraySet<Task> outClosingTasks) {
+    void getClosingTasks(ArraySet<ActivityRecord> closingApps, ArraySet<Task> outClosingTasks) {
         outClosingTasks.clear();
         for (int i = closingApps.size() - 1; i >= 0; i--) {
-            final AppWindowToken atoken = closingApps.valueAt(i);
-            final Task task = atoken.getTask();
+            final ActivityRecord activity = closingApps.valueAt(i);
+            final Task task = activity.getTask();
 
             // If the task of the app is not visible anymore, it means no other app in that task
             // is opening. Thus, the task is closing.
@@ -358,7 +358,7 @@
 
     @VisibleForTesting
     int getSnapshotMode(Task task) {
-        final AppWindowToken topChild = task.getTopChild();
+        final ActivityRecord topChild = task.getTopChild();
         if (!task.isActivityTypeStandardOrUndefined() && !task.isActivityTypeAssistant()) {
             return SNAPSHOT_MODE_NONE;
         } else if (topChild != null && topChild.shouldUseAppThemeSnapshot()) {
@@ -373,7 +373,7 @@
      * as possible by using the theme's window background.
      */
     private TaskSnapshot drawAppThemeSnapshot(Task task) {
-        final AppWindowToken topChild = task.getTopChild();
+        final ActivityRecord topChild = task.getTopChild();
         if (topChild == null) {
             return null;
         }
@@ -415,17 +415,17 @@
     }
 
     /**
-     * Called when an {@link AppWindowToken} has been removed.
+     * Called when an {@link ActivityRecord} has been removed.
      */
-    void onAppRemoved(AppWindowToken wtoken) {
-        mCache.onAppRemoved(wtoken);
+    void onAppRemoved(ActivityRecord activity) {
+        mCache.onAppRemoved(activity);
     }
 
     /**
-     * Called when the process of an {@link AppWindowToken} has died.
+     * Called when the process of an {@link ActivityRecord} has died.
      */
-    void onAppDied(AppWindowToken wtoken) {
-        mCache.onAppDied(wtoken);
+    void onAppDied(ActivityRecord activity) {
+        mCache.onAppDied(activity);
     }
 
     void notifyTaskRemovedFromRecents(int taskId, int userId) {
@@ -481,9 +481,9 @@
      *         {@param task}.
      */
     private int getSystemUiVisibility(Task task) {
-        final AppWindowToken topFullscreenToken = task.getTopFullscreenAppToken();
-        final WindowState topFullscreenWindow = topFullscreenToken != null
-                ? topFullscreenToken.getTopFullscreenWindow()
+        final ActivityRecord topFullscreenActivity = task.getTopFullscreenActivity();
+        final WindowState topFullscreenWindow = topFullscreenActivity != null
+                ? topFullscreenActivity.getTopFullscreenWindow()
                 : null;
         if (topFullscreenWindow != null) {
             return topFullscreenWindow.getSystemUiVisibility();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 172ebce..b1e5c8f 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -136,7 +136,7 @@
     private final int mOrientationOnCreation;
     private final SurfaceControl.Transaction mTransaction;
 
-    static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
+    static TaskSnapshotSurface create(WindowManagerService service, ActivityRecord activity,
             TaskSnapshot snapshot) {
 
         final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
@@ -159,23 +159,24 @@
         final int windowPrivateFlags;
         final int currentOrientation;
         synchronized (service.mGlobalLock) {
-            final WindowState mainWindow = token.findMainWindow();
-            final Task task = token.getTask();
+            final WindowState mainWindow = activity.findMainWindow();
+            final Task task = activity.getTask();
             if (task == null) {
-                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for token="
-                        + token);
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
+                        + activity);
                 return null;
             }
-            final AppWindowToken topFullscreenToken = token.getTask().getTopFullscreenAppToken();
-            if (topFullscreenToken == null) {
+            final ActivityRecord topFullscreenActivity =
+                    activity.getTask().getTopFullscreenActivity();
+            if (topFullscreenActivity == null) {
                 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
                         + task);
                 return null;
             }
-            final WindowState topFullscreenWindow = topFullscreenToken.getTopFullscreenWindow();
+            final WindowState topFullscreenWindow = topFullscreenActivity.getTopFullscreenWindow();
             if (mainWindow == null || topFullscreenWindow == null) {
-                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
-                        + token);
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
+                        + activity);
                 return null;
             }
             sysUiVis = topFullscreenWindow.getSystemUiVisibility();
@@ -191,7 +192,7 @@
                     | FLAG_NOT_FOCUSABLE
                     | FLAG_NOT_TOUCHABLE;
             layoutParams.privateFlags = windowPrivateFlags & PRIVATE_FLAG_INHERITS;
-            layoutParams.token = token.token;
+            layoutParams.token = activity.token;
             layoutParams.width = LayoutParams.MATCH_PARENT;
             layoutParams.height = LayoutParams.MATCH_PARENT;
             layoutParams.systemUiVisibility = sysUiVis;
@@ -207,7 +208,7 @@
         }
         try {
             final int res = session.addToDisplay(window, window.mSeq, layoutParams,
-                    View.GONE, token.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
+                    View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
                     tmpRect, tmpCutout, null, mTmpInsetsState);
             if (res < 0) {
                 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 10d8328..fc9a110 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -78,6 +78,7 @@
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.List;
 
 public class TaskStack extends WindowContainer<Task> implements
@@ -110,9 +111,9 @@
      */
     private final Rect mFullyAdjustedImeBounds = new Rect();
 
-    /** Application tokens that are exiting, but still on screen for animations. */
-    final AppTokenList mExitingAppTokens = new AppTokenList();
-    final AppTokenList mTmpAppTokens = new AppTokenList();
+    /** ActivityRecords that are exiting, but still on screen for animations. */
+    final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
+    final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
 
     /** Detach this stack from its display when animation completes. */
     // TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -153,8 +154,8 @@
     final Rect mTmpDimBoundsRect = new Rect();
     private final Point mLastSurfaceSize = new Point();
 
-    private final AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry =
-            new AnimatingAppWindowTokenRegistry();
+    private final AnimatingActivityRegistry mAnimatingActivityRegistry =
+            new AnimatingActivityRegistry();
 
     TaskStack(WindowManagerService service, int stackId, ActivityStack activityStack) {
         super(service);
@@ -676,11 +677,11 @@
             }
             mDisplayContent.setLayoutNeeded();
         }
-        for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
-            final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
-            if (wtoken.getTask() == task) {
-                wtoken.mIsExiting = false;
-                mExitingAppTokens.remove(appNdx);
+        for (int appNdx = mExitingActivities.size() - 1; appNdx >= 0; --appNdx) {
+            final ActivityRecord activity = mExitingActivities.get(appNdx);
+            if (activity.getTask() == task) {
+                activity.mIsExiting = false;
+                mExitingActivities.remove(appNdx);
             }
         }
     }
@@ -1327,18 +1328,18 @@
         for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
             mChildren.get(taskNdx).dump(pw, prefix + "  ", dumpAll);
         }
-        if (!mExitingAppTokens.isEmpty()) {
+        if (!mExitingActivities.isEmpty()) {
             pw.println();
             pw.println("  Exiting application tokens:");
-            for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
-                WindowToken token = mExitingAppTokens.get(i);
+            for (int i = mExitingActivities.size() - 1; i >= 0; i--) {
+                WindowToken token = mExitingActivities.get(i);
                 pw.print("  Exiting App #"); pw.print(i);
                 pw.print(' '); pw.print(token);
                 pw.println(':');
                 token.dump(pw, "    ", dumpAll);
             }
         }
-        mAnimatingAppWindowTokenRegistry.dump(pw, "AnimatingApps:", prefix);
+        mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix);
     }
 
     @Override
@@ -1435,8 +1436,8 @@
             Rect contentRect, Rect postExclude) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final Task task = mChildren.get(i);
-            AppWindowToken token = task.getTopVisibleAppToken();
-            if (token == null || !token.hasContentToDisplay()) {
+            ActivityRecord topVisibleActivity = task.getTopVisibleActivity();
+            if (topVisibleActivity == null || !topVisibleActivity.hasContentToDisplay()) {
                 continue;
             }
 
@@ -1747,7 +1748,7 @@
             if (homeTask == null) {
                 return true;
             }
-            final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
+            final ActivityRecord homeApp = homeTask.getTopVisibleActivity();
             if (!homeTask.isVisible() || homeApp == null) {
                 return true;
             }
@@ -1862,7 +1863,7 @@
         scheduleAnimation();
     }
 
-    AnimatingAppWindowTokenRegistry getAnimatingAppWindowTokenRegistry() {
-        return mAnimatingAppWindowTokenRegistry;
+    AnimatingActivityRegistry getAnimatingActivityRegistry() {
+        return mAnimatingActivityRegistry;
     }
 }
diff --git a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
index 01abcab..61e9e50 100644
--- a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
+++ b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
@@ -29,7 +29,7 @@
 import java.io.PrintWriter;
 
 /**
- * Manages the set of {@link AppWindowToken}s for which we don't know yet whether it's visible or
+ * Manages the set of {@link ActivityRecord}s for which we don't know yet whether it's visible or
  * not. This happens when starting an activity while the lockscreen is showing. In that case, the
  * keyguard flags an app might set influence it's visibility, so we wait until this is resolved to
  * start the transition to avoid flickers.
@@ -56,7 +56,7 @@
 
     // Set of apps for which we don't know yet whether it's visible or not, depending on what kind
     // of lockscreen flags the app might set during its first relayout.
-    private final ArrayMap<AppWindowToken, Integer> mUnknownApps = new ArrayMap<>();
+    private final ArrayMap<ActivityRecord, Integer> mUnknownApps = new ArrayMap<>();
 
     private final WindowManagerService mService;
 
@@ -87,52 +87,52 @@
         return builder.toString();
     }
 
-    void appRemovedOrHidden(@NonNull AppWindowToken appWindow) {
+    void appRemovedOrHidden(@NonNull ActivityRecord activity) {
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App removed or hidden appWindow=" + appWindow);
+            Slog.d(TAG, "App removed or hidden activity=" + activity);
         }
-        mUnknownApps.remove(appWindow);
+        mUnknownApps.remove(activity);
     }
 
     /**
-     * Notifies that {@param appWindow} has been launched behind Keyguard, and we need to wait until
+     * Notifies that {@param activity} has been launched behind Keyguard, and we need to wait until
      * it is resumed and relaid out to resolve the visibility.
      */
-    void notifyLaunched(@NonNull AppWindowToken appWindow) {
+    void notifyLaunched(@NonNull ActivityRecord activity) {
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App launched appWindow=" + appWindow);
+            Slog.d(TAG, "App launched activity=" + activity);
         }
-        mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RESUME);
+        mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_RESUME);
     }
 
     /**
-     * Notifies that {@param appWindow} has finished resuming.
+     * Notifies that {@param activity} has finished resuming.
      */
-    void notifyAppResumedFinished(@NonNull AppWindowToken appWindow) {
-        if (mUnknownApps.containsKey(appWindow)
-                && mUnknownApps.get(appWindow) == UNKNOWN_STATE_WAITING_RESUME) {
+    void notifyAppResumedFinished(@NonNull ActivityRecord activity) {
+        if (mUnknownApps.containsKey(activity)
+                && mUnknownApps.get(activity) == UNKNOWN_STATE_WAITING_RESUME) {
             if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-                Slog.d(TAG, "App resume finished appWindow=" + appWindow);
+                Slog.d(TAG, "App resume finished activity=" + activity);
             }
-            mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RELAYOUT);
+            mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_RELAYOUT);
         }
     }
 
     /**
-     * Notifies that {@param appWindow} has relaid out.
+     * Notifies that {@param activity} has relaid out.
      */
-    void notifyRelayouted(@NonNull AppWindowToken appWindow) {
-        if (!mUnknownApps.containsKey(appWindow)) {
+    void notifyRelayouted(@NonNull ActivityRecord activity) {
+        if (!mUnknownApps.containsKey(activity)) {
             return;
         }
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App relayouted appWindow=" + appWindow);
+            Slog.d(TAG, "App relayouted appWindow=" + activity);
         }
-        int state = mUnknownApps.get(appWindow);
+        int state = mUnknownApps.get(activity);
         if (state == UNKNOWN_STATE_WAITING_RELAYOUT) {
-            mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE);
+            mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE);
             mService.notifyKeyguardFlagsChanged(this::notifyVisibilitiesUpdated,
-                    appWindow.getDisplayContent().getDisplayId());
+                    activity.getDisplayContent().getDisplayId());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index e7b09db..1e13aef 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -118,7 +118,7 @@
         }
 
         mFindResults.resetTopWallpaper = true;
-        if (w.mAppToken != null && w.mAppToken.isHidden() && !w.mAppToken.isSelfAnimating()) {
+        if (w.mActivityRecord != null && w.mActivityRecord.isHidden() && !w.mActivityRecord.isSelfAnimating()) {
 
             // If this window's app token is hidden and not animating, it is of no interest to us.
             if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping hidden and not animating token: " + w);
@@ -135,10 +135,10 @@
             mFindResults.setUseTopWallpaperAsTarget(true);
         }
 
-        final boolean keyguardGoingAwayWithWallpaper = (w.mAppToken != null
-                && w.mAppToken.isSelfAnimating()
-                && AppTransition.isKeyguardGoingAwayTransit(w.mAppToken.getTransit())
-                && (w.mAppToken.getTransitFlags()
+        final boolean keyguardGoingAwayWithWallpaper = (w.mActivityRecord != null
+                && w.mActivityRecord.isSelfAnimating()
+                && AppTransition.isKeyguardGoingAwayTransit(w.mActivityRecord.getTransit())
+                && (w.mActivityRecord.getTransitFlags()
                         & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
 
         boolean needsShowWhenLockedWallpaper = false;
@@ -148,7 +148,7 @@
             // The lowest show when locked window decides whether we need to put the wallpaper
             // behind.
             needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
-                    || (w.mAppToken != null && !w.mAppToken.fillsParent());
+                    || (w.mActivityRecord != null && !w.mActivityRecord.fillsParent());
         }
 
         if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
@@ -159,8 +159,8 @@
 
         final RecentsAnimationController recentsAnimationController =
                 mService.getRecentsAnimationController();
-        final boolean animationWallpaper = w.mAppToken != null && w.mAppToken.getAnimation() != null
-                && w.mAppToken.getAnimation().getShowWallpaper();
+        final boolean animationWallpaper = w.mActivityRecord != null && w.mActivityRecord.getAnimation() != null
+                && w.mActivityRecord.getAnimation().getShowWallpaper();
         final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
                 || animationWallpaper;
         final boolean isRecentsTransitionTarget = (recentsAnimationController != null
@@ -223,22 +223,22 @@
                 && recentsAnimationController.isWallpaperVisible(wallpaperTarget);
         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
-                + " animating=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
-                ? wallpaperTarget.mAppToken.isSelfAnimating() : null)
+                + " animating=" + ((wallpaperTarget != null && wallpaperTarget.mActivityRecord != null)
+                ? wallpaperTarget.mActivityRecord.isSelfAnimating() : null)
                 + " prev=" + mPrevWallpaperTarget
                 + " recentsAnimationWallpaperVisible=" + isAnimatingWithRecentsComponent);
         return (wallpaperTarget != null
                 && (!wallpaperTarget.mObscured
                         || isAnimatingWithRecentsComponent
-                        || (wallpaperTarget.mAppToken != null
-                                && wallpaperTarget.mAppToken.isSelfAnimating())))
+                        || (wallpaperTarget.mActivityRecord != null
+                                && wallpaperTarget.mActivityRecord.isSelfAnimating())))
                 || mPrevWallpaperTarget != null;
     }
 
     boolean isWallpaperTargetAnimating() {
         return mWallpaperTarget != null && mWallpaperTarget.isAnimating()
-                && (mWallpaperTarget.mAppToken == null
-                        || !mWallpaperTarget.mAppToken.isWaitingForTransitionStart());
+                && (mWallpaperTarget.mActivityRecord == null
+                        || !mWallpaperTarget.mActivityRecord.isWaitingForTransitionStart());
     }
 
     void updateWallpaperVisibility() {
@@ -527,10 +527,10 @@
             return;
         }
 
-        final boolean newTargetHidden = wallpaperTarget.mAppToken != null
-                && wallpaperTarget.mAppToken.hiddenRequested;
-        final boolean oldTargetHidden = prevWallpaperTarget.mAppToken != null
-                && prevWallpaperTarget.mAppToken.hiddenRequested;
+        final boolean newTargetHidden = wallpaperTarget.mActivityRecord != null
+                && wallpaperTarget.mActivityRecord.hiddenRequested;
+        final boolean oldTargetHidden = prevWallpaperTarget.mActivityRecord != null
+                && prevWallpaperTarget.mActivityRecord.hiddenRequested;
 
         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Animating wallpapers:" + " old: "
                 + prevWallpaperTarget + " hidden=" + oldTargetHidden + " new: " + wallpaperTarget
@@ -544,9 +544,9 @@
             // is not. If they're both hidden, still use the new target.
             mWallpaperTarget = prevWallpaperTarget;
         } else if (newTargetHidden == oldTargetHidden
-                && !mDisplayContent.mOpeningApps.contains(wallpaperTarget.mAppToken)
-                && (mDisplayContent.mOpeningApps.contains(prevWallpaperTarget.mAppToken)
-                || mDisplayContent.mClosingApps.contains(prevWallpaperTarget.mAppToken))) {
+                && !mDisplayContent.mOpeningApps.contains(wallpaperTarget.mActivityRecord)
+                && (mDisplayContent.mOpeningApps.contains(prevWallpaperTarget.mActivityRecord)
+                || mDisplayContent.mClosingApps.contains(prevWallpaperTarget.mActivityRecord))) {
             // If they're both hidden (or both not hidden), prefer the one that's currently in
             // opening or closing app list, this allows transition selection logic to better
             // determine the wallpaper status of opening/closing apps.
@@ -661,23 +661,23 @@
      * Adjusts the wallpaper windows if the input display has a pending wallpaper layout or one of
      * the opening apps should be a wallpaper target.
      */
-    void adjustWallpaperWindowsForAppTransitionIfNeeded(ArraySet<AppWindowToken> openingApps,
-            ArraySet<AppWindowToken> changingApps) {
+    void adjustWallpaperWindowsForAppTransitionIfNeeded(ArraySet<ActivityRecord> openingApps,
+            ArraySet<ActivityRecord> changingApps) {
         boolean adjust = false;
         if ((mDisplayContent.pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
             adjust = true;
         } else {
             for (int i = openingApps.size() - 1; i >= 0; --i) {
-                final AppWindowToken token = openingApps.valueAt(i);
-                if (token.windowsCanBeWallpaperTarget()) {
+                final ActivityRecord activity = openingApps.valueAt(i);
+                if (activity.windowsCanBeWallpaperTarget()) {
                     adjust = true;
                     break;
                 }
             }
             if (!adjust) {
                 for (int i = changingApps.size() - 1; i >= 0; --i) {
-                    final AppWindowToken token = changingApps.valueAt(i);
-                    if (token.windowsCanBeWallpaperTarget()) {
+                    final ActivityRecord activity = changingApps.valueAt(i);
+                    if (activity.windowsCanBeWallpaperTarget()) {
                         adjust = true;
                         break;
                     }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a4ab66a..037edf1 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -947,9 +947,9 @@
         wrapper.release();
     }
 
-    void forAllAppWindows(Consumer<AppWindowToken> callback) {
+    void forAllActivities(Consumer<ActivityRecord> callback) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
-            mChildren.get(i).forAllAppWindows(callback);
+            mChildren.get(i).forAllActivities(callback);
         }
     }
 
@@ -1446,7 +1446,7 @@
         final WindowManagerPolicy policy = mWmService.mPolicy;
         forAllWindows(w -> {
             final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
-            if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
+            if (w.isVisibleLw() && (w.mActivityRecord != null || keyguard)) {
                 w.mWinAnimator.mDrawState = DRAW_PENDING;
                 // Force add to mResizingWindows.
                 w.resetLastContentInsets();
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 0cb4826..d224972 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -216,7 +216,7 @@
      *
      * @param displayId The logical display id.
      * @param callbacks The callbacks to invoke.
-     * @return {@code false} if display id is not valid.
+     * @return {@code false} if display id is not valid or an embedded display.
      */
     public abstract boolean setMagnificationCallbacks(int displayId,
             @Nullable MagnificationCallbacks callbacks);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c485280..caa2c01 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -531,7 +531,7 @@
      * List of app window tokens that are waiting for replacing windows. If the
      * replacement doesn't come in time the stale windows needs to be disposed of.
      */
-    final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
+    final ArrayList<ActivityRecord> mWindowReplacementTimeouts = new ArrayList<>();
 
     /**
      * Windows that are being resized.  Used so we can tell the client about
@@ -880,7 +880,7 @@
     /** The display that the rotation animation is applying to. */
     private int mFrozenDisplayId;
 
-    /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
+    /** Skip repeated ActivityRecords initialization. Note that AppWindowsToken's version of this
      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     int mTransactionSequence;
 
@@ -990,7 +990,7 @@
         @Override
         public void onAppTransitionFinishedLocked(IBinder token) {
             mAtmInternal.notifyAppTransitionFinished();
-            final AppWindowToken atoken = mRoot.getAppWindowToken(token);
+            final ActivityRecord atoken = mRoot.getActivityRecord(token);
             if (atoken == null) {
                 return;
             }
@@ -1368,7 +1368,7 @@
                 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
             }
 
-            AppWindowToken atoken = null;
+            ActivityRecord activity = null;
             final boolean hasParent = parentWindow != null;
             // Use existing parent window token for child windows since they go in the same token
             // as there parent window so we can apply the same policy on them.
@@ -1434,16 +1434,16 @@
                         session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);
             } else if (rootType >= FIRST_APPLICATION_WINDOW
                     && rootType <= LAST_APPLICATION_WINDOW) {
-                atoken = token.asAppWindowToken();
-                if (atoken == null) {
+                activity = token.asActivityRecord();
+                if (activity == null) {
                     ProtoLog.w(WM_ERROR, "Attempted to add window with non-application token "
                             + ".%s Aborting.", token);
                     return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
-                } else if (atoken.removed) {
+                } else if (activity.removed) {
                     ProtoLog.w(WM_ERROR, "Attempted to add window with exiting application token "
                             + ".%s Aborting.", token);
                     return WindowManagerGlobal.ADD_APP_EXITING;
-                } else if (type == TYPE_APPLICATION_STARTING && atoken.startingWindow != null) {
+                } else if (type == TYPE_APPLICATION_STARTING && activity.startingWindow != null) {
                     ProtoLog.w(WM_ERROR,
                             "Attempted to add starting window to token with already existing"
                                     + " starting window");
@@ -1495,8 +1495,8 @@
                             + "%s.  Aborting.", attrs.token);
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-            } else if (token.asAppWindowToken() != null) {
-                ProtoLog.w(WM_ERROR, "Non-null appWindowToken for system window of rootType=%d",
+            } else if (token.asActivityRecord() != null) {
+                ProtoLog.w(WM_ERROR, "Non-null activity for system window of rootType=%d",
                         rootType);
                 // It is not valid to use an app token with other system types; we will
                 // instead make a new token for it (as if null had been passed in for the token).
@@ -1591,11 +1591,11 @@
             final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
             win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
 
-            final AppWindowToken aToken = token.asAppWindowToken();
-            if (type == TYPE_APPLICATION_STARTING && aToken != null) {
-                aToken.startingWindow = win;
+            final ActivityRecord tokenActivity = token.asActivityRecord();
+            if (type == TYPE_APPLICATION_STARTING && tokenActivity != null) {
+                tokenActivity.startingWindow = win;
                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
-                        aToken, win);
+                        activity, win);
             }
 
             boolean imMayMove = true;
@@ -1636,12 +1636,12 @@
             winAnimator.mEnterAnimationPending = true;
             winAnimator.mEnteringAnimation = true;
             // Check if we need to prepare a transition for replacing window first.
-            if (atoken != null && atoken.isVisible()
-                    && !prepareWindowReplacementTransition(atoken)) {
+            if (activity != null && activity.isVisible()
+                    && !prepareWindowReplacementTransition(activity)) {
                 // If not, check if need to set up a dummy transition during display freeze
                 // so that the unfreeze wait for the apps to draw. This might be needed if
                 // the app is relaunching.
-                prepareNoneTransitionForRelaunching(atoken);
+                prepareNoneTransitionForRelaunching(activity);
             }
 
             final DisplayFrames displayFrames = displayContent.mDisplayFrames;
@@ -1651,10 +1651,10 @@
                     displayContent.calculateDisplayCutoutForRotation(displayInfo.rotation));
             final Rect taskBounds;
             final boolean floatingStack;
-            if (atoken != null && atoken.getTask() != null) {
+            if (activity != null && activity.getTask() != null) {
                 taskBounds = mTmpRect;
-                atoken.getTask().getBounds(mTmpRect);
-                floatingStack = atoken.getTask().isFloating();
+                tokenActivity.getTask().getBounds(mTmpRect);
+                floatingStack = activity.getTask().isFloating();
             } else {
                 taskBounds = null;
                 floatingStack = false;
@@ -1663,12 +1663,12 @@
                     outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
                 res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
             }
-            outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
+            outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win));
 
             if (mInTouchMode) {
                 res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
             }
-            if (win.mAppToken == null || !win.mAppToken.isClientHidden()) {
+            if (win.mActivityRecord == null || !win.mActivityRecord.isClientHidden()) {
                 res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
             }
 
@@ -1753,8 +1753,8 @@
             WindowState attachedWindow) {
         // Try using the target SDK of the root window
         if (attachedWindow != null) {
-            return attachedWindow.mAppToken != null
-                    && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O;
+            return attachedWindow.mActivityRecord != null
+                    && attachedWindow.mActivityRecord.mTargetSdk >= Build.VERSION_CODES.O;
         } else {
             // Otherwise, look at the package
             try {
@@ -1778,9 +1778,9 @@
     /**
      * Returns true if we're done setting up any transitions.
      */
-    private boolean prepareWindowReplacementTransition(AppWindowToken atoken) {
-        atoken.clearAllDrawn();
-        final WindowState replacedWindow = atoken.getReplacingWindow();
+    private boolean prepareWindowReplacementTransition(ActivityRecord activity) {
+        activity.clearAllDrawn();
+        final WindowState replacedWindow = activity.getReplacingWindow();
         if (replacedWindow == null) {
             // We expect to already receive a request to remove the old window. If it did not
             // happen, let's just simply add a window.
@@ -1791,8 +1791,8 @@
         Rect frame = replacedWindow.getVisibleFrameLw();
         // We treat this as if this activity was opening, so we can trigger the app transition
         // animation and piggy-back on existing transition animation infrastructure.
-        final DisplayContent dc = atoken.getDisplayContent();
-        dc.mOpeningApps.add(atoken);
+        final DisplayContent dc = activity.getDisplayContent();
+        dc.mOpeningApps.add(activity);
         dc.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT,
                 0 /* flags */, false /* forceOverride */);
         dc.mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
@@ -1801,14 +1801,14 @@
         return true;
     }
 
-    private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) {
+    private void prepareNoneTransitionForRelaunching(ActivityRecord activity) {
         // Set up a none-transition and add the app to opening apps, so that the display
         // unfreeze wait for the apps to be drawn.
         // Note that if the display unfroze already because app unfreeze timed out,
         // we don't set up the transition anymore and just let it go.
-        final DisplayContent dc = atoken.getDisplayContent();
-        if (mDisplayFrozen && !dc.mOpeningApps.contains(atoken) && atoken.isRelaunching()) {
-            dc.mOpeningApps.add(atoken);
+        final DisplayContent dc = activity.getDisplayContent();
+        if (mDisplayFrozen && !dc.mOpeningApps.contains(activity) && activity.isRelaunching()) {
+            dc.mOpeningApps.add(activity);
             dc.prepareAppTransition(WindowManager.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT, 0 /* flags */,
                     false /* forceOverride */);
             dc.executeAppTransition();
@@ -1885,26 +1885,26 @@
         }
 
         final WindowToken token = win.mToken;
-        final AppWindowToken atoken = win.mAppToken;
+        final ActivityRecord activity = win.mActivityRecord;
         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing %s from %s", win, token);
         // Window will already be removed from token before this post clean-up method is called.
         if (token.isEmpty()) {
             if (!token.mPersistOnEmpty) {
                 token.removeImmediately();
-            } else if (atoken != null) {
-                // TODO: Should this be moved into AppWindowToken.removeWindow? Might go away after
+            } else if (activity != null) {
+                // TODO: Should this be moved into ActivityRecord.removeWindow? Might go away after
                 // re-factor.
-                atoken.firstWindowDrawn = false;
-                atoken.clearAllDrawn();
-                final TaskStack stack = atoken.getStack();
+                activity.firstWindowDrawn = false;
+                activity.clearAllDrawn();
+                final TaskStack stack = activity.getStack();
                 if (stack != null) {
-                    stack.mExitingAppTokens.remove(atoken);
+                    stack.mExitingActivities.remove(activity);
                 }
             }
         }
 
-        if (atoken != null) {
-            atoken.postWindowRemoveStartingWindowCleanup(win);
+        if (activity != null) {
+            activity.postWindowRemoveStartingWindowCleanup(win);
         }
 
         if (win.mAttrs.type == TYPE_WALLPAPER) {
@@ -1917,8 +1917,8 @@
         if (dc != null && !mWindowPlacerLocked.isInLayout()) {
             dc.assignWindowLayers(true /* setLayoutNeeded */);
             mWindowPlacerLocked.performSurfacePlacement();
-            if (win.mAppToken != null) {
-                win.mAppToken.updateReportedVisibilityLocked();
+            if (win.mActivityRecord != null) {
+                win.mActivityRecord.updateReportedVisibilityLocked();
             }
         }
 
@@ -2125,9 +2125,9 @@
                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
                     win.mLayoutNeeded = true;
                 }
-                if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
+                if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
                         || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
-                    win.mAppToken.checkKeyguardFlagsChanged();
+                    win.mActivityRecord.checkKeyguardFlagsChanged();
                 }
                 if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
                         && (mAccessibilityController != null)) {
@@ -2196,8 +2196,8 @@
             // We should only relayout if the view is visible, it is a starting window, or the
             // associated appToken is not hidden.
             final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
-                    (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
-                            || !win.mAppToken.isClientHidden());
+                    (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
+                            || !win.mActivityRecord.isClientHidden());
 
             // If we are not currently running the exit animation, we need to see about starting
             // one.
@@ -2302,8 +2302,8 @@
                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
             }
 
-            if (win.mAppToken != null) {
-                displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
+            if (win.mActivityRecord != null) {
+                displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mActivityRecord);
             }
 
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientation");
@@ -2315,8 +2315,8 @@
                 displayContent.mWallpaperController.updateWallpaperOffset(
                         win, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
             }
-            if (win.mAppToken != null) {
-                win.mAppToken.updateReportedVisibilityLocked();
+            if (win.mActivityRecord != null) {
+                win.mActivityRecord.updateReportedVisibilityLocked();
             }
             if (winAnimator.mReportSurfaceResized) {
                 winAnimator.mReportSurfaceResized = false;
@@ -2356,7 +2356,7 @@
                     outStableInsets, outOutsets);
             outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
             outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
-            outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
+            outInsetsState.set(displayContent.getInsetsPolicy().getInsetsForDispatch(win));
             if (DEBUG) {
                 Slog.v(TAG_WM, "Relayout given client " + client.asBinder()
                         + ", requestedWidth=" + requestedWidth
@@ -2414,8 +2414,8 @@
             if (displayContent.mInputMethodWindow == win) {
                 displayContent.setInputMethodWindowLocked(null);
             }
-            boolean stopped = win.mAppToken != null ? win.mAppToken.mAppStopped : true;
-            // We set mDestroying=true so AppWindowToken#notifyAppStopped in-to destroy surfaces
+            boolean stopped = win.mActivityRecord != null ? win.mActivityRecord.mAppStopped : true;
+            // We set mDestroying=true so ActivityRecord#notifyAppStopped in-to destroy surfaces
             // will later actually destroy the surface if we do not do so here. Normally we leave
             // this to the exit animation.
             win.mDestroying = true;
@@ -2652,11 +2652,11 @@
     void initializeRecentsAnimation(int targetActivityType,
             IRecentsAnimationRunner recentsAnimationRunner,
             RecentsAnimationController.RecentsAnimationCallbacks callbacks, int displayId,
-            SparseBooleanArray recentTaskIds) {
+            SparseBooleanArray recentTaskIds, ActivityRecord targetActivity) {
         mRecentsAnimationController = new RecentsAnimationController(this, recentsAnimationRunner,
                 callbacks, displayId);
         mRoot.getDisplayContent(displayId).mAppTransition.updateBooster();
-        mRecentsAnimationController.initialize(targetActivityType, recentTaskIds);
+        mRecentsAnimationController.initialize(targetActivityType, recentTaskIds, targetActivity);
     }
 
     @VisibleForTesting
@@ -2700,7 +2700,7 @@
     }
 
     void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
-        final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
+        final ActivityRecord wtoken = mRoot.getActivityRecord(token);
         if (wtoken != null) {
             wtoken.setMainWindowOpaque(isOpaque);
         }
@@ -4338,7 +4338,7 @@
         // to make room for IME, but the window is not the focused window that's taking input.
         // TODO (b/111080190): Consider the case of multiple IMEs on multi-display.
         final DisplayContent topFocusedDisplay = mRoot.getTopFocusedDisplayContent();
-        final AppWindowToken focusedApp = topFocusedDisplay.mFocusedApp;
+        final ActivityRecord focusedApp = topFocusedDisplay.mFocusedApp;
         return (focusedApp != null && focusedApp.getTask() != null)
                 ? focusedApp.getTask().mStack : null;
     }
@@ -4823,8 +4823,8 @@
                 case WINDOW_REPLACEMENT_TIMEOUT: {
                     synchronized (mGlobalLock) {
                         for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
-                            final AppWindowToken token = mWindowReplacementTimeouts.get(i);
-                            token.onWindowReplacementTimeout();
+                            final ActivityRecord activity = mWindowReplacementTimeouts.get(i);
+                            activity.onWindowReplacementTimeout();
                         }
                         mWindowReplacementTimeouts.clear();
                     }
@@ -5574,6 +5574,20 @@
     }
 
     @Override
+    public void hideTransientBars(int displayId) {
+        mAtmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.STATUS_BAR,
+                "hideTransientBars()");
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent != null) {
+                displayContent.hideTransientBars();
+            } else {
+                Slog.w(TAG, "hideTransientBars with invalid displayId=" + displayId);
+            }
+        }
+    }
+
+    @Override
     public void setForceShowSystemBars(boolean show) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -5997,7 +6011,7 @@
 
                 mRoot.forAllWindows((w) -> {
                     if ((!visibleOnly || w.mWinAnimator.getShown())
-                            && (!appsOnly || w.mAppToken != null)) {
+                            && (!appsOnly || w.mActivityRecord != null)) {
                         windows.add(w);
                     }
                 }, true /* traverseTopToBottom */);
@@ -6032,16 +6046,16 @@
      * the time an ANR occurred before anything else in the system changes
      * in response.
      *
-     * @param appWindowToken The application that ANR'd, may be null.
+     * @param activity The application that ANR'd, may be null.
      * @param windowState The window that ANR'd, may be null.
      * @param reason The reason for the ANR, may be null.
      */
-    void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState, String reason) {
+    void saveANRStateLocked(ActivityRecord activity, WindowState windowState, String reason) {
         StringWriter sw = new StringWriter();
         PrintWriter pw = new FastPrintWriter(sw, false, 1024);
         pw.println("  ANR time: " + DateFormat.getDateTimeInstance().format(new Date()));
-        if (appWindowToken != null) {
-            pw.println("  Application at fault: " + appWindowToken.stringName);
+        if (activity != null) {
+            pw.println("  Application at fault: " + activity.stringName);
         }
         if (windowState != null) {
             pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
@@ -6287,19 +6301,19 @@
      * @param token Application token for which the activity will be relaunched.
      */
     void setWillReplaceWindow(IBinder token, boolean animate) {
-        final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
-        if (appWindowToken == null) {
+        final ActivityRecord activity = mRoot.getActivityRecord(token);
+        if (activity == null) {
             ProtoLog.w(WM_ERROR, "Attempted to set replacing window on non-existing app token %s",
                     token);
             return;
         }
-        if (!appWindowToken.hasContentToDisplay()) {
+        if (!activity.hasContentToDisplay()) {
             ProtoLog.w(WM_ERROR,
                     "Attempted to set replacing window on app token with no content %s",
                     token);
             return;
         }
-        appWindowToken.setWillReplaceWindows(animate);
+        activity.setWillReplaceWindows(animate);
     }
 
     /**
@@ -6316,14 +6330,14 @@
     // above. We should combine them or find better names.
     void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
         synchronized (mGlobalLock) {
-            final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
-            if (appWindowToken == null) {
+            final ActivityRecord activity = mRoot.getActivityRecord(token);
+            if (activity == null) {
                 ProtoLog.w(WM_ERROR,
                         "Attempted to set replacing window on non-existing app token %s",
                         token);
                 return;
             }
-            if (!appWindowToken.hasContentToDisplay()) {
+            if (!activity.hasContentToDisplay()) {
                 ProtoLog.w(WM_ERROR,
                         "Attempted to set replacing window on app token with no content %s",
                         token);
@@ -6331,9 +6345,9 @@
             }
 
             if (childrenOnly) {
-                appWindowToken.setWillReplaceChildWindows();
+                activity.setWillReplaceChildWindows();
             } else {
-                appWindowToken.setWillReplaceWindows(false /* animate */);
+                activity.setWillReplaceWindows(false /* animate */);
             }
 
             scheduleClearWillReplaceWindows(token, true /* replacing */);
@@ -6350,22 +6364,22 @@
      * @param replacing Whether the window is being replaced or not.
      */
     void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
-        final AppWindowToken appWindowToken = mRoot.getAppWindowToken(token);
-        if (appWindowToken == null) {
+        final ActivityRecord activity = mRoot.getActivityRecord(token);
+        if (activity == null) {
             ProtoLog.w(WM_ERROR, "Attempted to reset replacing window on non-existing app token %s",
                     token);
             return;
         }
         if (replacing) {
-            scheduleWindowReplacementTimeouts(appWindowToken);
+            scheduleWindowReplacementTimeouts(activity);
         } else {
-            appWindowToken.clearWillReplaceWindows();
+            activity.clearWillReplaceWindows();
         }
     }
 
-    void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) {
-        if (!mWindowReplacementTimeouts.contains(appWindowToken)) {
-            mWindowReplacementTimeouts.add(appWindowToken);
+    void scheduleWindowReplacementTimeouts(ActivityRecord activity) {
+        if (!mWindowReplacementTimeouts.contains(activity)) {
+            mWindowReplacementTimeouts.add(activity);
         }
         mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
         mH.sendEmptyMessageDelayed(
@@ -7317,6 +7331,9 @@
             synchronized (mGlobalLock) {
                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
                 if (dc != null && dc.mInputMethodTarget != null) {
+                    // If there was a pending IME show(), reset it as IME has been
+                    // requested to be hidden.
+                    dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
                     dc.mInputMethodTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
                 }
             }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 1c0d156..eb75684 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -773,6 +773,12 @@
 
     @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public int computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback) {
+        // Since there could be more than one activities in a process record, we don't need to
+        // compute the OomAdj with each of them, just need to find out the activity with the
+        // "best" state, the order would be visible, pausing, stopping...
+        ActivityStack.ActivityState best = DESTROYED;
+        boolean finishing = true;
+        boolean visible = false;
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             final int activitiesSize = mActivities.size();
             for (int j = 0; j < activitiesSize; j++) {
@@ -788,7 +794,6 @@
                     }
                 }
                 if (r.visible) {
-                    callback.onVisibleActivity();
                     final TaskRecord task = r.getTaskRecord();
                     if (task != null && minTaskLayer > 0) {
                         final int layer = task.mLayerRank;
@@ -796,16 +801,32 @@
                             minTaskLayer = layer;
                         }
                     }
-                    break;
-                } else if (r.isState(PAUSING, PAUSED)) {
-                    callback.onPausedActivity();
-                } else if (r.isState(STOPPING)) {
-                    callback.onStoppingActivity(r.finishing);
+                    visible = true;
+                    // continue the loop, in case there are multiple visible activities in
+                    // this process, we'd find out the one with the minimal layer, thus it'll
+                    // get a higher adj score.
                 } else {
-                    callback.onOtherActivity();
+                    if (best != PAUSING && best != PAUSED) {
+                        if (r.isState(PAUSING, PAUSED)) {
+                            best = PAUSING;
+                        } else if (r.isState(STOPPING)) {
+                            best = STOPPING;
+                            // Not "finishing" if any of activity isn't finishing.
+                            finishing &= r.finishing;
+                        }
+                    }
                 }
             }
         }
+        if (visible) {
+            callback.onVisibleActivity();
+        } else if (best == PAUSING) {
+            callback.onPausedActivity();
+        } else if (best == STOPPING) {
+            callback.onStoppingActivity(finishing);
+        } else {
+            callback.onOtherActivity();
+        }
 
         return minTaskLayer;
     }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7ff9b70..b9cf29a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -31,6 +31,7 @@
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
@@ -191,6 +192,7 @@
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
 import android.view.InputWindowHandle;
+import android.view.InsetsState;
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
@@ -249,7 +251,7 @@
     final WindowId mWindowId;
     WindowToken mToken;
     // The same object as mToken if this is an app window and null for non-app windows.
-    AppWindowToken mAppToken;
+    ActivityRecord mActivityRecord;
 
     // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
     // modified they will need to be locked.
@@ -633,11 +635,20 @@
      */
     private boolean mIsDimming = false;
 
-    private @Nullable InsetsSourceProvider mInsetProvider;
+    private @Nullable InsetsSourceProvider mControllableInsetProvider;
+    private InsetsState mClientInsetsState = new InsetsState();
 
     private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
     private KeyInterceptionInfo mKeyInterceptionInfo;
 
+    InsetsState getClientInsetsState() {
+        return mClientInsetsState;
+    }
+
+    void setClientInsetsState(InsetsState state) {
+        mClientInsetsState = state;
+    }
+
     void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
             @Rotation int rotation, boolean requested) {
         // Invisible windows and the wallpaper do not participate in the seamless rotation animation
@@ -691,7 +702,7 @@
         final boolean immersiveSticky =
                 (mSystemUiVisibility & immersiveStickyFlags) == immersiveStickyFlags;
         return immersiveSticky && mWmService.mSystemGestureExcludedByPreQStickyImmersive
-                && mAppToken != null && mAppToken.mTargetSdk < Build.VERSION_CODES.Q;
+                && mActivityRecord != null && mActivityRecord.mTargetSdk < Build.VERSION_CODES.Q;
     }
 
     void setLastExclusionHeights(int side, int requested, int granted) {
@@ -741,7 +752,7 @@
         mClient = c;
         mAppOp = appOp;
         mToken = token;
-        mAppToken = mToken.asAppWindowToken();
+        mActivityRecord = mToken.asActivityRecord();
         mOwnerUid = ownerId;
         mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
         mWindowId = new WindowId(this);
@@ -805,7 +816,7 @@
         }
         mIsFloatingLayer = mIsImWindow || mIsWallpaper;
 
-        if (mAppToken != null && mAppToken.mShowForAllUsers) {
+        if (mActivityRecord != null && mActivityRecord.mShowForAllUsers) {
             // Windows for apps that can show for all users should also show when the device is
             // locked.
             mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
@@ -820,7 +831,8 @@
         mLastRequestedHeight = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, getDisplayId());
+                mActivityRecord != null ? mActivityRecord.mInputApplicationHandle : null,
+                    getDisplayId());
     }
 
     void attach() {
@@ -835,7 +847,7 @@
      */
     boolean inSizeCompatMode() {
         return (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0
-                || (mAppToken != null && mAppToken.hasSizeCompatBounds()
+                || (mActivityRecord != null && mActivityRecord.hasSizeCompatBounds()
                         // Exclude starting window because it is not displayed by the application.
                         && mAttrs.type != TYPE_APPLICATION_STARTING);
     }
@@ -950,11 +962,11 @@
             layoutYDiff = 0;
         } else {
             mWindowFrames.mContainingFrame.set(getDisplayedBounds());
-            if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
+            if (mActivityRecord != null && !mActivityRecord.mFrozenBounds.isEmpty()) {
 
                 // If the bounds are frozen, we still want to translate the window freely and only
                 // freeze the size.
-                Rect frozen = mAppToken.mFrozenBounds.peek();
+                Rect frozen = mActivityRecord.mFrozenBounds.peek();
                 mWindowFrames.mContainingFrame.right =
                         mWindowFrames.mContainingFrame.left + frozen.width();
                 mWindowFrames.mContainingFrame.bottom =
@@ -1137,8 +1149,8 @@
     // TODO: Look into whether this override is still necessary.
     @Override
     public Rect getBounds() {
-        if (mAppToken != null) {
-            return mAppToken.getBounds();
+        if (mActivityRecord != null) {
+            return mActivityRecord.getBounds();
         } else {
             return super.getBounds();
         }
@@ -1239,12 +1251,12 @@
 
     @Override
     public IApplicationToken getAppToken() {
-        return mAppToken != null ? mAppToken.appToken : null;
+        return mActivityRecord != null ? mActivityRecord.appToken : null;
     }
 
     @Override
     public boolean isVoiceInteraction() {
-        return mAppToken != null && mAppToken.mVoiceInteraction;
+        return mActivityRecord != null && mActivityRecord.mVoiceInteraction;
     }
 
     boolean setReportResizeHints() {
@@ -1303,8 +1315,8 @@
 
             // If it's a dead window left on screen, and the configuration changed, there is nothing
             // we can do about it. Remove the window now.
-            if (mAppToken != null && mAppDied) {
-                mAppToken.removeDeadWindows();
+            if (mActivityRecord != null && mAppDied) {
+                mActivityRecord.removeDeadWindows();
                 return;
             }
 
@@ -1328,8 +1340,8 @@
                             this, winAnimator.mSurfaceController);
                 }
                 winAnimator.mDrawState = DRAW_PENDING;
-                if (mAppToken != null) {
-                    mAppToken.clearAllDrawn();
+                if (mActivityRecord != null) {
+                    mActivityRecord.clearAllDrawn();
                 }
             }
             if (!mWmService.mResizingWindows.contains(this)) {
@@ -1401,7 +1413,7 @@
     }
 
     Task getTask() {
-        return mAppToken != null ? mAppToken.getTask() : null;
+        return mActivityRecord != null ? mActivityRecord.getTask() : null;
     }
 
     TaskStack getStack() {
@@ -1450,14 +1462,14 @@
     }
 
     public long getInputDispatchingTimeoutNanos() {
-        return mAppToken != null
-                ? mAppToken.mInputDispatchingTimeoutNanos
+        return mActivityRecord != null
+                ? mActivityRecord.mInputDispatchingTimeoutNanos
                 : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
     }
 
     @Override
     public boolean hasAppShownWindows() {
-        return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
+        return mActivityRecord != null && (mActivityRecord.firstWindowDrawn || mActivityRecord.startingDisplayed);
     }
 
     boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
@@ -1492,7 +1504,8 @@
         return wouldBeVisibleIfPolicyIgnored() && isVisibleByPolicy()
                 // If we don't have a provider, this window isn't used as a window generating
                 // insets, so nobody can hide it over the inset APIs.
-                && (mInsetProvider == null || mInsetProvider.isClientVisible());
+                && (mControllableInsetProvider == null
+                        || mControllableInsetProvider.isClientVisible());
     }
 
     /**
@@ -1537,7 +1550,7 @@
      */
     // TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
     boolean isWinVisibleLw() {
-        return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.isSelfAnimating())
+        return (mActivityRecord == null || !mActivityRecord.hiddenRequested || mActivityRecord.isSelfAnimating())
                 && isVisible();
     }
 
@@ -1565,7 +1578,7 @@
      * call to IWindowSession.add() and the first relayout().
      */
     boolean isVisibleOrAdding() {
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
                 && isVisibleByPolicy() && !isParentWindowHidden()
                 && (atoken == null || !atoken.hiddenRequested)
@@ -1581,7 +1594,7 @@
         if (!mHasSurface || mDestroying || !isVisibleByPolicy()) {
             return false;
         }
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         if (atoken != null) {
             return ((!isParentWindowHidden() && !atoken.hiddenRequested)
                     || isAnimating());
@@ -1605,8 +1618,8 @@
      * it must be drawn before allDrawn can become true.
      */
     boolean isInteresting() {
-        return mAppToken != null && !mAppDied
-                && (!mAppToken.isFreezingScreen() || !mAppFreezing)
+        return mActivityRecord != null && !mAppDied
+                && (!mActivityRecord.isFreezingScreen() || !mAppFreezing)
                 && mViewVisibility == View.VISIBLE;
     }
 
@@ -1631,14 +1644,14 @@
         if (translucent) {
             return false;
         }
-        if (mAppToken == null) {
+        if (mActivityRecord == null) {
             final boolean shown = mWinAnimator.getShown();
             final boolean exiting = mAnimatingExit || mDestroying;
             return shown && !exiting;
         } else {
             final Task task = getTask();
             final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
-            return canFromTask && !mAppToken.isHidden();
+            return canFromTask && !mActivityRecord.isHidden();
         }
     }
 
@@ -1648,7 +1661,7 @@
      */
     @Override
     public boolean isDisplayedLw() {
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         return isDrawnLw() && isVisibleByPolicy()
                 && ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested))
                         || isAnimating());
@@ -1664,7 +1677,7 @@
 
     @Override
     public boolean isGoneForLayoutLw() {
-        final AppWindowToken atoken = mAppToken;
+        final ActivityRecord atoken = mActivityRecord;
         return mViewVisibility == View.GONE
                 || !mRelayoutCalled
                 || (atoken == null && mToken.isHidden())
@@ -1727,7 +1740,7 @@
             // Starting window that's exiting will be removed when the animation finishes.
             // Mark all relevant flags for that onExitAnimationDone will proceed all the way
             // to actually remove it.
-            if (!visible && isVisibleNow() && mAppToken.isSelfAnimating()) {
+            if (!visible && isVisibleNow() && mActivityRecord.isSelfAnimating()) {
                 mAnimatingExit = true;
                 mRemoveOnExit = true;
                 mWindowRemovalAllowed = true;
@@ -2004,8 +2017,8 @@
                             + "callers=%s",
                     this, mWinAnimator.mSurfaceController, mAnimatingExit, mRemoveOnExit,
                     mHasSurface, mWinAnimator.getShown(), isAnimating(),
-                    mAppToken != null && mAppToken.isSelfAnimating(), mWillReplaceWindow,
-                    mAppToken != null && mAppToken.inPendingTransaction,
+                    mActivityRecord != null && mActivityRecord.isSelfAnimating(), mWillReplaceWindow,
+                    mActivityRecord != null && mActivityRecord.inPendingTransaction,
                     mWmService.mDisplayFrozen, Debug.getCallers(6));
 
             // Visibility of the removed window. Will be used later to update orientation later on.
@@ -2064,9 +2077,9 @@
                     }
                 }
                 final boolean isAnimating = isAnimating()
-                        && (mAppToken == null || !mAppToken.isWaitingForTransitionStart());
-                final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null
-                        && mAppToken.isLastWindow(this);
+                        && (mActivityRecord == null || !mActivityRecord.isWaitingForTransitionStart());
+                final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
+                        && mActivityRecord.isLastWindow(this);
                 // We delay the removal of a window if it has a showing surface that can be used to run
                 // exit animation and it is marked as exiting.
                 // Also, If isn't the an animating starting window that is the last window in the app.
@@ -2078,8 +2091,8 @@
                     ProtoLog.v(WM_DEBUG_ADD_REMOVE,
                             "Not removing %s due to exit animation", this);
                     setupWindowForRemoveOnExit();
-                    if (mAppToken != null) {
-                        mAppToken.updateReportedVisibilityLocked();
+                    if (mActivityRecord != null) {
+                        mActivityRecord.updateReportedVisibilityLocked();
                     }
                     return;
                 }
@@ -2127,7 +2140,7 @@
             return false;
         }
 
-        final boolean windowsAreFocusable = mAppToken == null || mAppToken.windowsAreFocusable();
+        final boolean windowsAreFocusable = mActivityRecord == null || mActivityRecord.windowsAreFocusable();
         if (!windowsAreFocusable) {
             // This window can't be an IME target if the app's windows should not be focusable.
             return false;
@@ -2160,8 +2173,8 @@
                         + " policyVisAfterAnim=" + mLegacyPolicyVisibilityAfterAnim
                         + " parentHidden=" + isParentWindowHidden()
                         + " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
-                if (mAppToken != null) {
-                    Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
+                if (mActivityRecord != null) {
+                    Slog.i(TAG_WM, "  mActivityRecord.hiddenRequested=" + mActivityRecord.hiddenRequested);
                 }
             }
         }
@@ -2306,8 +2319,8 @@
         final Region region = inputWindowHandle.touchableRegion;
         setTouchableRegionCropIfNeeded(inputWindowHandle);
 
-        final Rect appOverrideBounds = mAppToken != null
-                ? mAppToken.getResolvedOverrideBounds() : null;
+        final Rect appOverrideBounds = mActivityRecord != null
+                ? mActivityRecord.getResolvedOverrideBounds() : null;
         if (appOverrideBounds != null && !appOverrideBounds.isEmpty()) {
             // There may have touchable letterboxes around the activity, so in order to let the
             // letterboxes are able to receive touch event and slip to activity, the activity with
@@ -2320,22 +2333,22 @@
                 // Non-modal uses the application based frame.
                 mTmpRect.set(mWindowFrames.mCompatFrame);
             }
-            // The offset of compatibility bounds is applied to surface of {@link #AppWindowToken}
+            // The offset of compatibility bounds is applied to surface of {@link #ActivityRecord}
             // and frame, so it is unnecessary to translate twice in surface based coordinates.
-            final int surfaceOffsetX = mAppToken.hasSizeCompatBounds()
-                    ? mAppToken.getBounds().left : 0;
+            final int surfaceOffsetX = mActivityRecord.hasSizeCompatBounds()
+                    ? mActivityRecord.getBounds().left : 0;
             mTmpRect.offset(surfaceOffsetX - mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
             region.set(mTmpRect);
             return flags;
         }
 
-        if (modal && mAppToken != null) {
+        if (modal && mActivityRecord != null) {
             // Limit the outer touch to the activity stack region.
             flags |= FLAG_NOT_TOUCH_MODAL;
             // If the inner bounds of letterbox is available, then it will be used as the touchable
             // region so it won't cover the touchable letterbox and the touch events can slip to
             // activity from letterbox.
-            mAppToken.getLetterboxInnerBounds(mTmpRect);
+            mActivityRecord.getLetterboxInnerBounds(mTmpRect);
             if (mTmpRect.isEmpty()) {
                 // If this is a modal window we need to dismiss it if it's not full screen and the
                 // touch happens outside of the frame that displays the content. This means we need
@@ -2426,7 +2439,7 @@
     void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
         // We need to turn on screen regardless of visibility.
         final boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0
-                || (mAppToken != null && mAppToken.canTurnScreenOn());
+                || (mActivityRecord != null && mActivityRecord.canTurnScreenOn());
 
         // The screen will turn on if the following conditions are met
         // 1. The window has the flag FLAG_TURN_SCREEN_ON or ActivityRecord#canTurnScreenOn.
@@ -2443,7 +2456,7 @@
             boolean allowTheaterMode = mWmService.mAllowTheaterModeWakeFromLayout
                     || Settings.Global.getInt(mWmService.mContext.getContentResolver(),
                             Settings.Global.THEATER_MODE_ON, 0) == 0;
-            boolean canTurnScreenOn = mAppToken == null || mAppToken.currentLaunchCanTurnScreenOn();
+            boolean canTurnScreenOn = mActivityRecord == null || mActivityRecord.currentLaunchCanTurnScreenOn();
 
             if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) {
                 if (DEBUG_VISIBILITY || DEBUG_POWER) {
@@ -2453,8 +2466,8 @@
                         PowerManager.WAKE_REASON_APPLICATION, "android.server.wm:SCREEN_ON_FLAG");
             }
 
-            if (mAppToken != null) {
-                mAppToken.setCurrentLaunchCanTurnScreenOn(false);
+            if (mActivityRecord != null) {
+                mActivityRecord.setCurrentLaunchCanTurnScreenOn(false);
             }
         }
 
@@ -2505,14 +2518,14 @@
     }
 
     void adjustStartingWindowFlags() {
-        if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null
-                && mAppToken.startingWindow != null) {
+        if (mAttrs.type == TYPE_BASE_APPLICATION && mActivityRecord != null
+                && mActivityRecord.startingWindow != null) {
             // Special handling of starting window over the base
             // window of the app: propagate lock screen flags to it,
             // to provide the correct semantics while starting.
             final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD
                     | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
-            WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs;
+            WindowManager.LayoutParams sa = mActivityRecord.startingWindow.mAttrs;
             sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask);
         }
     }
@@ -2544,8 +2557,8 @@
                     Slog.i(TAG, "WIN DEATH: " + win);
                     if (win != null) {
                         final DisplayContent dc = getDisplayContent();
-                        if (win.mAppToken != null && win.mAppToken.findMainWindow() == win) {
-                            mWmService.mTaskSnapshotController.onAppDied(win.mAppToken);
+                        if (win.mActivityRecord != null && win.mActivityRecord.findMainWindow() == win) {
+                            mWmService.mTaskSnapshotController.onAppDied(win.mActivityRecord);
                         }
                         win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
                         if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
@@ -2587,7 +2600,7 @@
      * interacts with it.
      */
     private boolean shouldKeepVisibleDeadAppWindow() {
-        if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) {
+        if (!isWinVisibleLw() || mActivityRecord == null || mActivityRecord.isClientHidden()) {
             // Not a visible app window or the app isn't dead.
             return false;
         }
@@ -2612,26 +2625,26 @@
         return isVisibleOrAdding()
                 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
-                && (mAppToken == null || mAppToken.windowsAreFocusable())
+                && (mActivityRecord == null || mActivityRecord.windowsAreFocusable())
                 && !cantReceiveTouchInput();
     }
 
     @Override
     public boolean canShowWhenLocked() {
         final boolean showBecauseOfActivity =
-                mAppToken != null && mAppToken.canShowWhenLocked();
+                mActivityRecord != null && mActivityRecord.canShowWhenLocked();
         final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
         return showBecauseOfActivity || showBecauseOfWindow;
     }
 
     /** @return false if this window desires touch events. */
     boolean cantReceiveTouchInput() {
-        if (mAppToken == null || mAppToken.getTask() == null) {
+        if (mActivityRecord == null || mActivityRecord.getTask() == null) {
             return false;
         }
 
-        return mAppToken.getTask().mStack.shouldIgnoreInput()
-                || mAppToken.hiddenRequested
+        return mActivityRecord.getTask().mStack.shouldIgnoreInput()
+                || mActivityRecord.hiddenRequested
                 || isAnimatingToRecents();
     }
 
@@ -2643,7 +2656,7 @@
                 mWmService.getRecentsAnimationController();
         return recentsAnimationController != null
                 && recentsAnimationController.isAnimatingTask(getTask())
-                && !recentsAnimationController.isTargetApp(mAppToken);
+                && !recentsAnimationController.isTargetApp(mActivityRecord);
     }
 
     @Override
@@ -2883,7 +2896,7 @@
     }
 
     boolean isClosing() {
-        return mAnimatingExit || (mAppToken != null && mAppToken.isClosingOrEnteringPip());
+        return mAnimatingExit || (mActivityRecord != null && mActivityRecord.isClosingOrEnteringPip());
     }
 
     void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {
@@ -2898,7 +2911,7 @@
     void sendAppVisibilityToClients() {
         super.sendAppVisibilityToClients();
 
-        final boolean clientHidden = mAppToken.isClientHidden();
+        final boolean clientHidden = mActivityRecord.isClientHidden();
         if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
             // Don't hide the starting window.
             return;
@@ -2993,10 +3006,10 @@
             mDestroying = false;
             destroyedSomething = true;
 
-            // Since mDestroying will affect AppWindowToken#allDrawn, we need to perform another
+            // Since mDestroying will affect ActivityRecord#allDrawn, we need to perform another
             // traversal in case we are waiting on this window to start the transition.
             if (getDisplayContent().mAppTransition.isTransitionSet()
-                    && getDisplayContent().mOpeningApps.contains(mAppToken)) {
+                    && getDisplayContent().mOpeningApps.contains(mActivityRecord)) {
                 mWmService.mWindowPlacerLocked.requestTraversal();
             }
         }
@@ -3076,7 +3089,7 @@
         // Child windows are evaluated based on their parent window.
         final WindowState win = getTopParentWindow();
         if (win.mAttrs.type < FIRST_SYSTEM_WINDOW
-                && win.mAppToken != null && win.mAppToken.mShowForAllUsers) {
+                && win.mActivityRecord != null && win.mActivityRecord.mShowForAllUsers) {
 
             // All window frames that are fullscreen extend above status bar, but some don't extend
             // below navigation bar. Thus, check for display frame for top/left and stable frame for
@@ -3216,8 +3229,8 @@
 
     @Override
     public Configuration getConfiguration() {
-        if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) {
-            return mAppToken.mFrozenMergedConfig.peek();
+        if (mActivityRecord != null && mActivityRecord.mFrozenMergedConfig.size() > 0) {
+            return mActivityRecord.mFrozenMergedConfig.peek();
         }
 
         // If the process has not registered to any display to listen to the configuration change,
@@ -3350,7 +3363,7 @@
     void notifyInsetsChanged() {
         try {
             mClient.insetsChanged(
-                    getDisplayContent().getInsetsStateController().getInsetsForDispatch(this));
+                    getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this));
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to deliver inset state change", e);
         }
@@ -3360,8 +3373,9 @@
     public void notifyInsetsControlChanged() {
         final InsetsStateController stateController =
                 getDisplayContent().getInsetsStateController();
+        final InsetsPolicy policy = getDisplayContent().getInsetsPolicy();
         try {
-            mClient.insetsControlChanged(stateController.getInsetsForDispatch(this),
+            mClient.insetsControlChanged(policy.getInsetsForDispatch(this),
                     stateController.getControlsForDispatch(this));
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to deliver inset state change", e);
@@ -3386,6 +3400,11 @@
         }
     }
 
+    @Override
+    public boolean canShowTransient() {
+        return (mAttrs.insetsFlags.behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0;
+    }
+
     Rect getBackdropFrame(Rect frame) {
         // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
         // start even if we haven't received the relayout window, so that the client requests
@@ -3453,7 +3472,7 @@
 
     /** Is this window in a container that takes up the entire screen space? */
     private boolean inAppWindowThatMatchesParentBounds() {
-        return mAppToken == null || (mAppToken.matchParentBounds() && !inMultiWindowMode());
+        return mActivityRecord == null || (mActivityRecord.matchParentBounds() && !inMultiWindowMode());
     }
 
     /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or
@@ -3465,8 +3484,8 @@
 
     @Override
     public boolean isLetterboxedForDisplayCutoutLw() {
-        if (mAppToken == null) {
-            // Only windows with an AppWindowToken are letterboxed.
+        if (mActivityRecord == null) {
+            // Only windows with an ActivityRecord are letterboxed.
             return false;
         }
         if (!mWindowFrames.parentFrameWasClippedByDisplayCutout()) {
@@ -3491,14 +3510,14 @@
      * @throws NullPointerException if there is no app window token for this window
      */
     private boolean frameCoversEntireAppTokenBounds() {
-        mTmpRect.set(mAppToken.getBounds());
+        mTmpRect.set(mActivityRecord.getBounds());
         mTmpRect.intersectUnchecked(mWindowFrames.mFrame);
-        return mAppToken.getBounds().equals(mTmpRect);
+        return mActivityRecord.getBounds().equals(mTmpRect);
     }
 
     @Override
     public boolean isLetterboxedOverlappingWith(Rect rect) {
-        return mAppToken != null && mAppToken.isLetterboxOverlappingWith(rect);
+        return mActivityRecord != null && mActivityRecord.isLetterboxOverlappingWith(rect);
     }
 
     boolean isDragResizeChanged() {
@@ -3554,7 +3573,7 @@
         // simulate that we are still resizing so the app fills the hole with the resizing
         // background.
         return (getDisplayContent().mDividerControllerLocked.isResizing()
-                        || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
+                        || mActivityRecord != null && !mActivityRecord.mFrozenBounds.isEmpty()) &&
                 !task.inFreeformWindowingMode() && !isGoneForLayoutLw();
 
     }
@@ -3674,8 +3693,8 @@
         }
         if (dumpAll) {
             pw.println(prefix + "mToken=" + mToken);
-            if (mAppToken != null) {
-                pw.println(prefix + "mAppToken=" + mAppToken);
+            if (mActivityRecord != null) {
+                pw.println(prefix + "mActivityRecord=" + mActivityRecord);
                 pw.print(prefix + "mAppDied=" + mAppDied);
                 pw.print(prefix + "drawnStateEvaluated=" + getDrawnStateEvaluated());
                 pw.println(prefix + "mightAffectAllDrawn=" + mightAffectAllDrawn());
@@ -4077,8 +4096,8 @@
 
     @Override
     public int getRotationAnimationHint() {
-        if (mAppToken != null) {
-            return mAppToken.mRotationAnimationHint;
+        if (mActivityRecord != null) {
+            return mActivityRecord.mRotationAnimationHint;
         } else {
             return -1;
         }
@@ -4101,8 +4120,8 @@
 
         final int drawState = mWinAnimator.mDrawState;
         if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW)
-                && mAttrs.type != TYPE_APPLICATION_STARTING && mAppToken != null) {
-            mAppToken.onFirstWindowDrawn(this, mWinAnimator);
+                && mAttrs.type != TYPE_APPLICATION_STARTING && mActivityRecord != null) {
+            mActivityRecord.onFirstWindowDrawn(this, mWinAnimator);
         }
 
         if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
@@ -4156,11 +4175,11 @@
                     + " during animation: policyVis=" + isVisibleByPolicy()
                     + " parentHidden=" + isParentWindowHidden()
                     + " tok.hiddenRequested="
-                    + (mAppToken != null && mAppToken.hiddenRequested)
-                    + " tok.hidden=" + (mAppToken != null && mAppToken.isHidden())
+                    + (mActivityRecord != null && mActivityRecord.hiddenRequested)
+                    + " tok.hidden=" + (mActivityRecord != null && mActivityRecord.isHidden())
                     + " animating=" + isAnimating()
                     + " tok animating="
-                    + (mAppToken != null && mAppToken.isSelfAnimating())
+                    + (mActivityRecord != null && mActivityRecord.isSelfAnimating())
                     + " Callers=" + Debug.getCallers(4));
         }
     }
@@ -4171,8 +4190,8 @@
         windowInfo.type = mAttrs.type;
         windowInfo.layer = mLayer;
         windowInfo.token = mClient.asBinder();
-        if (mAppToken != null) {
-            windowInfo.activityToken = mAppToken.appToken.asBinder();
+        if (mActivityRecord != null) {
+            windowInfo.activityToken = mActivityRecord.appToken.asBinder();
         }
         windowInfo.title = mAttrs.accessibilityTitle;
         // Panel windows have no public way to set the a11y title directly. Use the
@@ -4402,7 +4421,7 @@
             mWmService.requestTraversal();
             // System windows don't have an activity and an app token as a result, but need a way
             // to be informed about their entrance animation end.
-            if (mAppToken == null) {
+            if (mActivityRecord == null) {
                 try {
                     mClient.dispatchWindowShown();
                 } catch (RemoteException e) {
@@ -4436,8 +4455,8 @@
         // care to ensure the activity has actually stopped and the surface is not still in use.
         // Otherwise we add the service to mDestroySurface and allow it to be processed in our next
         // transaction.
-        if (mAppToken != null) {
-            mAppToken.destroySurfaces();
+        if (mActivityRecord != null) {
+            mActivityRecord.destroySurfaces();
         } else {
             if (hasSurface) {
                 mWmService.mDestroySurface.add(this);
@@ -4564,7 +4583,7 @@
                         + " pv=" + isVisibleByPolicy()
                         + " mDrawState=" + mWinAnimator.mDrawState
                         + " ph=" + isParentWindowHidden()
-                        + " th=" + (mAppToken != null ? mAppToken.hiddenRequested : false)
+                        + " th=" + (mActivityRecord != null ? mActivityRecord.hiddenRequested : false)
                         + " a=" + isAnimating());
             }
         }
@@ -4590,7 +4609,7 @@
         }
 
         // But if we have a frame, and are an application window, then we must be cropped.
-        if (mAppToken != null) {
+        if (mActivityRecord != null) {
             return false;
         }
 
@@ -4814,7 +4833,7 @@
     void startAnimation(Animation anim) {
 
         // If we are an inset provider, all our animations are driven by the inset client.
-        if (mInsetProvider != null && mInsetProvider.isControllable()) {
+        if (mControllableInsetProvider != null) {
             return;
         }
 
@@ -4834,7 +4853,7 @@
     private void startMoveAnimation(int left, int top) {
 
         // If we are an inset provider, all our animations are driven by the inset client.
-        if (mInsetProvider != null && mInsetProvider.isControllable()) {
+        if (mControllableInsetProvider != null) {
             return;
         }
 
@@ -4905,9 +4924,9 @@
         outMatrix.setValues(float9);
     }
 
-    // TODO: Hack to work around the number of states AppWindowToken needs to access without having
+    // TODO: Hack to work around the number of states ActivityRecord needs to access without having
     // access to its windows children. Need to investigate re-writing
-    // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
+    // {@link ActivityRecord#updateReportedVisibilityLocked} so this can be removed.
     static final class UpdateReportedVisibilityResults {
         int numInteresting;
         int numVisible;
@@ -4989,9 +5008,9 @@
     boolean needsZBoost() {
         final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget;
         if (mIsImWindow && inputMethodTarget != null) {
-            final AppWindowToken appToken = inputMethodTarget.mAppToken;
-            if (appToken != null) {
-                return appToken.needsZBoost();
+            final ActivityRecord activity = inputMethodTarget.mActivityRecord;
+            if (activity != null) {
+                return activity.needsZBoost();
             }
         }
         return mWillReplaceWindow;
@@ -5131,7 +5150,7 @@
             if (getParentWindow().isInputMethodTarget()) {
                 return true;
             }
-        } else if (mAppToken != null) {
+        } else if (mActivityRecord != null) {
             // Likewise if we share a token with the Input method target and are ordered
             // above it but not necessarily a child (e.g. a Dialog) then we also need
             // this promotion.
@@ -5318,12 +5337,22 @@
         mWindowFrames.setContentChanged(false);
     }
 
-    void setInsetProvider(InsetsSourceProvider insetProvider) {
-        mInsetProvider = insetProvider;
+    /**
+     * Set's an {@link InsetsSourceProvider} to be associated with this window, but only if the
+     * provider itself is controllable, as one window can be the provider of more than one inset
+     * type (i.e. gesture insets). If this window is controllable, all its animations must be
+     * controlled by its control target, and the visibility of this window should be taken account
+     * into the state of the control target.
+     *
+     * @param insetProvider the provider which should not be visible to the client.
+     * @see InsetsStateController#getInsetsForDispatch(WindowState)
+     */
+    void setControllableInsetProvider(InsetsSourceProvider insetProvider) {
+        mControllableInsetProvider = insetProvider;
     }
 
-    InsetsSourceProvider getInsetProvider() {
-        return mInsetProvider;
+    InsetsSourceProvider getControllableInsetProvider() {
+        return mControllableInsetProvider;
     }
 
     private final class MoveAnimationSpec implements AnimationSpec {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index eac372f..3f25f89 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -266,7 +266,7 @@
         if (DEBUG_ANIM) Slog.v(
                 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
                         + ", reportedVisible="
-                        + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
+                        + (mWin.mActivityRecord != null ? mWin.mActivityRecord.reportedVisible : false));
 
         mWin.checkPolicyVisibilityChange();
         final DisplayContent displayContent = mWin.getDisplayContent();
@@ -285,8 +285,8 @@
                     "WindowStateAnimator", displayContent.pendingLayoutChanges);
         }
 
-        if (mWin.mAppToken != null) {
-            mWin.mAppToken.updateReportedVisibilityLocked();
+        if (mWin.mActivityRecord != null) {
+            mWin.mActivityRecord.updateReportedVisibilityLocked();
         }
     }
 
@@ -358,8 +358,8 @@
         }
         mDrawState = READY_TO_SHOW;
         boolean result = false;
-        final AppWindowToken atoken = mWin.mAppToken;
-        if (atoken == null || atoken.canShowWindows()
+        final ActivityRecord activity = mWin.mActivityRecord;
+        if (activity == null || activity.canShowWindows()
                 || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
             result = mWin.performShowLocked();
         }
@@ -409,7 +409,7 @@
                 // we are just doing an in-place switch. In that case any SurfaceFlinger side
                 // child layers need to be reparented to the new surface to make this
                 // transparent to the app.
-                if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
+                if (mWin.mActivityRecord == null || mWin.mActivityRecord.isRelaunching() == false) {
                     mPostDrawTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
                             mSurfaceController.mSurfaceControl)
                             .apply();
@@ -431,16 +431,16 @@
     void resetDrawState() {
         mDrawState = DRAW_PENDING;
 
-        if (mWin.mAppToken == null) {
+        if (mWin.mActivityRecord == null) {
             return;
         }
 
-        if (!mWin.mAppToken.isSelfAnimating()) {
-            mWin.mAppToken.clearAllDrawn();
+        if (!mWin.mActivityRecord.isSelfAnimating()) {
+            mWin.mActivityRecord.clearAllDrawn();
         } else {
             // Currently animating, persist current state of allDrawn until animation
             // is complete.
-            mWin.mAppToken.deferClearAllDrawn = true;
+            mWin.mActivityRecord.deferClearAllDrawn = true;
         }
     }
 
@@ -588,10 +588,10 @@
     }
 
     void destroySurfaceLocked() {
-        final AppWindowToken wtoken = mWin.mAppToken;
-        if (wtoken != null) {
-            if (mWin == wtoken.startingWindow) {
-                wtoken.startingDisplayed = false;
+        final ActivityRecord activity = mWin.mActivityRecord;
+        if (activity != null) {
+            if (mWin == activity.startingWindow) {
+                activity.startingDisplayed = false;
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 5b362c3..ad71237 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -243,7 +243,7 @@
         return false;
     }
 
-    AppWindowToken asAppWindowToken() {
+    ActivityRecord asActivityRecord() {
         // TODO: Not sure if this is the best way to handle this vs. using instanceof and casting.
         // I am not an app window token!
         return null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 59996cc..5a1d552 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -62,4 +62,6 @@
             String packageName, boolean hasGrant) {
         return false;
     }
+
+    public void setLocationEnabled(ComponentName who, boolean locationEnabled) {}
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6f643c9..5e49c7a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -86,6 +86,7 @@
 import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
@@ -167,6 +168,7 @@
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.location.LocationManager;
 import android.media.AudioManager;
 import android.media.IAudioService;
 import android.net.ConnectivityManager;
@@ -1958,6 +1960,10 @@
             return mContext.getSystemService(ConnectivityManager.class);
         }
 
+        LocationManager getLocationManager() {
+            return mContext.getSystemService(LocationManager.class);
+        }
+
         IWindowManager getIWindowManager() {
             return IWindowManager.Stub
                     .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -4177,7 +4183,7 @@
     private boolean passwordQualityInvocationOrderCheckEnabled(String packageName, int userId) {
         try {
             return mIPlatformCompat.isChangeEnabledByPackageName(ADMIN_APP_PASSWORD_COMPLEXITY,
-                    packageName);
+                    packageName, userId);
         } catch (RemoteException e) {
             Log.e(LOG_TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
         }
@@ -4819,7 +4825,7 @@
      */
     private PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle, boolean parent) {
         if (!mHasFeature) {
-            new PasswordMetrics(LockPatternUtils.CREDENTIAL_TYPE_NONE);
+            new PasswordMetrics(CREDENTIAL_TYPE_NONE);
         }
         enforceFullCrossUsersPermission(userHandle);
         ArrayList<PasswordMetrics> adminMetrics = new ArrayList<>();
@@ -5176,11 +5182,19 @@
     private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
             int flags, int callingUid, int userHandle) {
         synchronized (getLockObject()) {
-            // TODO(b/120484642): remove getBytes() below
             final PasswordMetrics minMetrics = getPasswordMinimumMetrics(userHandle);
-            final List<PasswordValidationError> validationErrors =
-                    PasswordMetrics.validatePassword(
-                            minMetrics, PASSWORD_COMPLEXITY_NONE, false, password.getBytes());
+            final List<PasswordValidationError> validationErrors;
+            // TODO: Consider changing validation API to take LockscreenCredential.
+            if (password.isEmpty()) {
+                validationErrors = PasswordMetrics.validatePasswordMetrics(
+                        minMetrics, PASSWORD_COMPLEXITY_NONE, false /* isPin */,
+                        new PasswordMetrics(CREDENTIAL_TYPE_NONE));
+            } else {
+                // TODO(b/120484642): remove getBytes() below
+                validationErrors = PasswordMetrics.validatePassword(
+                        minMetrics, PASSWORD_COMPLEXITY_NONE, false, password.getBytes());
+            }
+
             if (!validationErrors.isEmpty()) {
                 Log.w(LOG_TAG, "Failed to reset password due to constraint violation: "
                         + validationErrors.get(0));
@@ -10890,6 +10904,36 @@
     }
 
     @Override
+    public void setLocationEnabled(ComponentName who, boolean locationEnabled) {
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        int userId = mInjector.userHandleGetCallingUserId();
+
+        synchronized (getLockObject()) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            if (!isDeviceOwner(who, userId) && !isCurrentUserDemo()) {
+                throw new SecurityException(
+                        "Permission denial: Profile owners cannot update location settings");
+            }
+        }
+
+        long ident = mInjector.binderClearCallingIdentity();
+        try {
+            mInjector.getLocationManager().setLocationEnabledForUser(
+                    locationEnabled, UserHandle.of(userId));
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.SET_SECURE_SETTING)
+                    .setAdmin(who)
+                    .setStrings(Settings.Secure.LOCATION_MODE, Integer.toString(
+                            locationEnabled ? Settings.Secure.LOCATION_MODE_ON
+                                    : Settings.Secure.LOCATION_MODE_OFF))
+                    .write();
+        } finally {
+            mInjector.binderRestoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
     public boolean setTime(ComponentName who, long millis) {
         Preconditions.checkNotNull(who, "ComponentName is null in setTime");
         enforceDeviceOwner(who);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 88859a7..5883048 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -90,6 +90,7 @@
 import com.android.server.camera.CameraServiceProxy;
 import com.android.server.clipboard.ClipboardService;
 import com.android.server.compat.PlatformCompat;
+import com.android.server.compat.PlatformCompatNative;
 import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.coverage.CoverageService;
@@ -641,8 +642,10 @@
         // Platform compat service is used by ActivityManagerService, PackageManagerService, and
         // possibly others in the future. b/135010838.
         t.traceBegin("PlatformCompat");
-        ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE,
-                new PlatformCompat(mSystemContext));
+        PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
+        ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
+        ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE,
+                new PlatformCompatNative(platformCompat));
         t.traceEnd();
 
         // Wait for installd to finish starting up so that it has a chance to
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 1ca96ed..08cdbfc 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,10 +1,14 @@
 java_library_static {
     name: "services.net",
-    srcs: ["java/**/*.java"],
+    srcs: [
+        ":tethering-services-srcs",
+        "java/**/*.java",
+    ],
     static_libs: [
         "dnsresolver_aidl_interface-V2-java",
         "netd_aidl_interface-java",
         "networkstack-client",
+        "tethering-client",
     ],
 }
 
@@ -17,3 +21,17 @@
         "java/android/net/netlink/*.java",
     ],
 }
+
+filegroup {
+    name: "services-tethering-shared-srcs",
+    srcs: [
+        ":framework-annotations",
+        "java/android/net/ConnectivityModuleConnector.java",
+        "java/android/net/NetworkStackClient.java",
+        "java/android/net/ip/InterfaceController.java",
+        "java/android/net/util/InterfaceParams.java",
+        "java/android/net/util/NetdService.java",
+        "java/android/net/util/NetworkConstants.java",
+        "java/android/net/util/SharedLog.java"
+    ],
+}
diff --git a/services/net/java/android/net/netlink/InetDiagMessage.java b/services/net/java/android/net/netlink/InetDiagMessage.java
index 31a2556..ca07630 100644
--- a/services/net/java/android/net/netlink/InetDiagMessage.java
+++ b/services/net/java/android/net/netlink/InetDiagMessage.java
@@ -26,6 +26,7 @@
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.NETLINK_INET_DIAG;
 
+import android.annotation.Nullable;
 import android.net.util.SocketUtils;
 import android.system.ErrnoException;
 import android.util.Log;
@@ -53,7 +54,35 @@
     private static final int TIMEOUT_MS = 500;
 
     public static byte[] InetDiagReqV2(int protocol, InetSocketAddress local,
-                                       InetSocketAddress remote, int family, short flags) {
+            InetSocketAddress remote, int family, short flags) {
+        return InetDiagReqV2(protocol, local, remote, family, flags, 0 /* pad */,
+                0 /* idiagExt */, StructInetDiagReqV2.INET_DIAG_REQ_V2_ALL_STATES);
+    }
+
+    /**
+     * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException}
+     * if local and remote are not both null or both non-null.
+     *
+     * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
+     *                 IPPROTO_UDP, or IPPROTO_UDPLITE.
+     * @param local local socket address of the target socket. This will be packed into a
+     *              {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
+     *              local or remote address is null.
+     * @param remote remote socket address of the target socket. This will be packed into a
+     *              {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
+     *              local or remote address is null.
+     * @param family the ip family of the request message. This should be set to either AF_INET or
+     *               AF_INET6 for IPv4 or IPv6 sockets respectively.
+     * @param flags message flags. See &lt;linux_src&gt;/include/uapi/linux/netlink.h.
+     * @param pad for raw socket protocol specification.
+     * @param idiagExt a set of flags defining what kind of extended information to report.
+     * @param state a bit mask that defines a filter of socket states.
+     *
+     * @return bytes array representation of the message
+     **/
+    public static byte[] InetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
+            @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt,
+            int state) throws NullPointerException {
         final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
         final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
         byteBuffer.order(ByteOrder.nativeOrder());
@@ -63,9 +92,9 @@
         nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY;
         nlMsgHdr.nlmsg_flags = flags;
         nlMsgHdr.pack(byteBuffer);
+        final StructInetDiagReqV2 inetDiagReqV2 =
+                new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state);
 
-        final StructInetDiagReqV2 inetDiagReqV2 = new StructInetDiagReqV2(protocol, local, remote,
-                family);
         inetDiagReqV2.pack(byteBuffer);
         return bytes;
     }
diff --git a/services/net/java/android/net/netlink/StructInetDiagReqV2.java b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
index 49a9325..2268113 100644
--- a/services/net/java/android/net/netlink/StructInetDiagReqV2.java
+++ b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
@@ -16,10 +16,10 @@
 
 package android.net.netlink;
 
-import static java.nio.ByteOrder.BIG_ENDIAN;
+import android.annotation.Nullable;
+
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
 
 /**
  * struct inet_diag_req_v2
@@ -40,41 +40,58 @@
 public class StructInetDiagReqV2 {
     public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE;
 
-    private final byte sdiag_family;
-    private final byte sdiag_protocol;
-    private final StructInetDiagSockId id;
-    private final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
-
+    private final byte mSdiagFamily;
+    private final byte mSdiagProtocol;
+    private final byte mIdiagExt;
+    private final byte mPad;
+    private final StructInetDiagSockId mId;
+    private final int mState;
+    public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
 
     public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote,
-                               int family) {
-        sdiag_family = (byte) family;
-        sdiag_protocol = (byte) protocol;
-        id = new StructInetDiagSockId(local, remote);
+            int family) {
+        this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */,
+                INET_DIAG_REQ_V2_ALL_STATES);
+    }
+
+    public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
+            @Nullable InetSocketAddress remote, int family, int pad, int extension, int state)
+            throws NullPointerException {
+        mSdiagFamily = (byte) family;
+        mSdiagProtocol = (byte) protocol;
+        // Request for all sockets if no specific socket is requested. Specify the local and remote
+        // socket address information for target request socket.
+        if ((local == null) != (remote == null)) {
+            throw new NullPointerException("Local and remote must be both null or both non-null");
+        }
+        mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null);
+        mPad = (byte) pad;
+        mIdiagExt = (byte) extension;
+        mState = state;
     }
 
     public void pack(ByteBuffer byteBuffer) {
         // The ByteOrder must have already been set by the caller.
-        byteBuffer.put((byte) sdiag_family);
-        byteBuffer.put((byte) sdiag_protocol);
-        byteBuffer.put((byte) 0);
-        byteBuffer.put((byte) 0);
-        byteBuffer.putInt(INET_DIAG_REQ_V2_ALL_STATES);
-        id.pack(byteBuffer);
+        byteBuffer.put((byte) mSdiagFamily);
+        byteBuffer.put((byte) mSdiagProtocol);
+        byteBuffer.put((byte) mIdiagExt);
+        byteBuffer.put((byte) mPad);
+        byteBuffer.putInt(mState);
+        if (mId != null) mId.pack(byteBuffer);
     }
 
     @Override
     public String toString() {
-        final String familyStr = NetlinkConstants.stringForAddressFamily(sdiag_family);
-        final String protocolStr = NetlinkConstants.stringForAddressFamily(sdiag_protocol);
+        final String familyStr = NetlinkConstants.stringForAddressFamily(mSdiagFamily);
+        final String protocolStr = NetlinkConstants.stringForAddressFamily(mSdiagProtocol);
 
         return "StructInetDiagReqV2{ "
                 + "sdiag_family{" + familyStr + "}, "
                 + "sdiag_protocol{" + protocolStr + "}, "
-                + "idiag_ext{" + 0 + ")}, "
-                + "pad{" + 0 + "}, "
-                + "idiag_states{" + Integer.toHexString(INET_DIAG_REQ_V2_ALL_STATES) + "}, "
-                + id.toString()
+                + "idiag_ext{" + mIdiagExt + ")}, "
+                + "pad{" + mPad + "}, "
+                + "idiag_states{" + Integer.toHexString(mState) + "}, "
+                + ((mId != null) ? mId.toString() : "inet_diag_sockid=null")
                 + "}";
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 6e8b86a..9e7b805 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -34,7 +34,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.AlarmManagerService.ACTIVE_INDEX;
 import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
-import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_PAROLE_CHANGED;
+import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
 import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
@@ -53,6 +53,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atLeastOnce;
@@ -68,6 +69,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -83,6 +85,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.usage.AppStandbyInternal;
 
 import org.junit.After;
 import org.junit.Before;
@@ -106,7 +109,8 @@
 
     private long mAppStandbyWindow;
     private AlarmManagerService mService;
-    private UsageStatsManagerInternal.AppIdleStateChangeListener mAppStandbyListener;
+    private AppStandbyInternal.AppIdleStateChangeListener mAppStandbyListener;
+    private AlarmManagerService.ChargingReceiver mChargingReceiver;
     @Mock
     private ContentResolver mMockResolver;
     @Mock
@@ -116,6 +120,8 @@
     @Mock
     private UsageStatsManagerInternal mUsageStatsManagerInternal;
     @Mock
+    private AppStandbyInternal mAppStandbyInternal;
+    @Mock
     private AppStateTracker mAppStateTracker;
     @Mock
     private AlarmManagerService.ClockReceiver mClockReceiver;
@@ -254,6 +260,8 @@
         doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
         doReturn(null)
                 .when(() -> LocalServices.getService(DeviceIdleInternal.class));
+        doReturn(mAppStandbyInternal).when(
+                () -> LocalServices.getService(AppStandbyInternal.class));
         doReturn(mUsageStatsManagerInternal).when(
                 () -> LocalServices.getService(UsageStatsManagerInternal.class));
         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
@@ -286,10 +294,17 @@
         assertEquals(0, mService.mConstants.MIN_FUTURITY);
         assertEquals(0, mService.mConstants.MIN_INTERVAL);
         mAppStandbyWindow = mService.mConstants.APP_STANDBY_WINDOW;
-        ArgumentCaptor<UsageStatsManagerInternal.AppIdleStateChangeListener> captor =
-                ArgumentCaptor.forClass(UsageStatsManagerInternal.AppIdleStateChangeListener.class);
-        verify(mUsageStatsManagerInternal).addAppIdleStateChangeListener(captor.capture());
+        ArgumentCaptor<AppStandbyInternal.AppIdleStateChangeListener> captor =
+                ArgumentCaptor.forClass(AppStandbyInternal.AppIdleStateChangeListener.class);
+        verify(mAppStandbyInternal).addListener(captor.capture());
         mAppStandbyListener = captor.getValue();
+
+        ArgumentCaptor<AlarmManagerService.ChargingReceiver> chargingReceiverCaptor =
+                ArgumentCaptor.forClass(AlarmManagerService.ChargingReceiver.class);
+        verify(mMockContext).registerReceiver(chargingReceiverCaptor.capture(),
+                argThat((filter) -> filter.hasAction(BatteryManager.ACTION_CHARGING)
+                        && filter.hasAction(BatteryManager.ACTION_DISCHARGING)));
+        mChargingReceiver = chargingReceiverCaptor.getValue();
     }
 
     private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
@@ -724,17 +739,19 @@
     }
 
     private void assertAndHandleParoleChanged(boolean parole) {
-        mAppStandbyListener.onParoleStateChanged(parole);
+        mChargingReceiver.onReceive(mMockContext,
+                new Intent(parole ? BatteryManager.ACTION_CHARGING
+                        : BatteryManager.ACTION_DISCHARGING));
         final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
         verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
         final Message lastMessage = messageCaptor.getValue();
         assertEquals("Unexpected message send to handler", lastMessage.what,
-                APP_STANDBY_PAROLE_CHANGED);
+                CHARGING_STATUS_CHANGED);
         mService.mHandler.handleMessage(lastMessage);
     }
 
     @Test
-    public void testParole() throws Exception {
+    public void testCharging() throws Exception {
         setQuotasEnabled(true);
         final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET);
         when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index d0158e0..1f4656a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -45,7 +45,6 @@
 import android.app.IUidObserver;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
-import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -64,9 +63,14 @@
 import android.util.ArraySet;
 import android.util.Pair;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
 import com.android.server.AppStateTracker.Listener;
+import com.android.server.usage.AppStandbyInternal;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -85,14 +89,10 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
 /**
  * Tests for {@link AppStateTracker}
  *
- * Run with:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+ * Run with: atest com.android.server.AppStateTrackerTest
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -129,8 +129,8 @@
         }
 
         @Override
-        UsageStatsManagerInternal injectUsageStatsManagerInternal() {
-            return mMockUsageStatsManagerInternal;
+        AppStandbyInternal injectAppStandbyInternal() {
+            return mMockAppStandbyInternal;
         }
 
         @Override
@@ -176,7 +176,7 @@
     private PowerManagerInternal mMockPowerManagerInternal;
 
     @Mock
-    private UsageStatsManagerInternal mMockUsageStatsManagerInternal;
+    private AppStandbyInternal mMockAppStandbyInternal;
 
     private MockContentResolver mMockContentResolver;
 
@@ -272,7 +272,7 @@
 
         verify(mMockContext).registerReceiver(
                 receiverCaptor.capture(), any(IntentFilter.class));
-        verify(mMockUsageStatsManagerInternal).addAppIdleStateChangeListener(
+        verify(mMockAppStandbyInternal).addListener(
                 appIdleStateChangeListenerCaptor.capture());
 
         mIUidObserver = uidObserverArgumentCaptor.getValue();
@@ -685,10 +685,12 @@
         List<OpEntry> entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_1, UID_1, entries));
 
@@ -696,7 +698,8 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_2, UID_2, entries));
 
@@ -704,7 +707,8 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_ALLOWED));
+                AppOpsManager.MODE_ALLOWED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_1, UID_10_1, entries));
 
@@ -712,10 +716,12 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
         entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
-                AppOpsManager.MODE_IGNORED));
+                AppOpsManager.MODE_IGNORED,
+                new Pair[0]));
 
         ops.add(new PackageOps(PACKAGE_3, UID_10_3, entries));
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 8b3c85e..6dd1bd8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -141,8 +141,10 @@
 
         sService.mConstants = new ActivityManagerConstants(sContext, sService,
                 sContext.getMainThreadHandler());
+        ProcessList pr = new ProcessList();
+        pr.init(sService, new ActiveUids(sService, false));
         setFieldValue(ActivityManagerService.class, sService, "mProcessList",
-                new ProcessList());
+                pr);
         setFieldValue(ActivityManagerService.class, sService, "mHandler",
                 mock(ActivityManagerService.MainHandler.class));
         setFieldValue(ActivityManagerService.class, sService, "mProcessStats",
@@ -346,11 +348,13 @@
     public void testUpdateOomAdj_DoOne_RecentTasks() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
-        doReturn(true).when(app).hasRecentTasks();
+        doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
+        WindowProcessController wpc = app.getWindowProcessController();
+        doReturn(true).when(wpc).hasRecentTasks();
         app.lastTopTime = SystemClock.uptimeMillis();
         sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
         sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
-        doCallRealMethod().when(app).hasRecentTasks();
+        doCallRealMethod().when(wpc).hasRecentTasks();
 
         assertEquals(PROCESS_STATE_CACHED_RECENT, app.setProcState);
     }
@@ -459,7 +463,7 @@
         doReturn(mock(WindowProcessController.class)).when(app).getWindowProcessController();
         WindowProcessController wpc = app.getWindowProcessController();
         doReturn(true).when(wpc).isPreviousProcess();
-        doReturn(true).when(app).hasActivities();
+        doReturn(true).when(wpc).hasActivities();
         sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
         sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
 
@@ -644,7 +648,7 @@
         WindowProcessController wpc = app.getWindowProcessController();
         doReturn(false).when(wpc).isHomeProcess();
         doReturn(true).when(wpc).isPreviousProcess();
-        doReturn(true).when(app).hasActivities();
+        doReturn(true).when(wpc).hasActivities();
         ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
                 MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
         bindService(app, client, null, Context.BIND_ALLOW_OOM_MANAGEMENT, mock(IBinder.class));
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 06366cf..b6a7b09 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -162,12 +162,12 @@
         mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
 
         // Note an op that's allowed.
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
         List<PackageOps> loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
 
         // Note another op that's not allowed.
-        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null);
         loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
         assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
@@ -183,7 +183,7 @@
         // This op controls WIFI_SCAN
         mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);
 
-        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
@@ -191,7 +191,7 @@
 
         // Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
         mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
-        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ERRORED);
 
         assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
@@ -203,8 +203,8 @@
     public void testStatePersistence() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
         mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
-        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null);
         mAppOpsService.writeState();
 
         // Create a new app ops service, and initialize its state from XML.
@@ -221,7 +221,7 @@
     @Test
     public void testShutdown() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
         mAppOpsService.shutdown();
 
         // Create a new app ops service, and initialize its state from XML.
@@ -236,7 +236,7 @@
     @Test
     public void testGetOpsForPackage() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         // Query all ops
         List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
@@ -265,7 +265,7 @@
     @Test
     public void testPackageRemoved() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         List<PackageOps> loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -278,7 +278,7 @@
     @Test
     public void testPackageRemovedHistoricalOps() throws InterruptedException {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
         historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName,
@@ -317,7 +317,7 @@
     @Test
     public void testUidRemoved() {
         mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
-        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName);
+        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
 
         List<PackageOps> loggedOps = getLoggedOps();
         assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -339,18 +339,18 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
@@ -359,11 +359,11 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
@@ -372,12 +372,12 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid,
                 PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
     }
 
@@ -386,18 +386,18 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
@@ -406,25 +406,25 @@
         setupProcStateTests();
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isEqualTo(MODE_ALLOWED);
 
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
         // Second time to make sure that settle time is overcome
         Thread.sleep(50);
         mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
-        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName))
+        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
                 .isNotEqualTo(MODE_ALLOWED);
     }
 
diff --git a/services/tests/servicestests/res/raw/apex_test.apex b/services/tests/servicestests/res/raw/apex_test.apex
new file mode 100644
index 0000000..19b1c5e
--- /dev/null
+++ b/services/tests/servicestests/res/raw/apex_test.apex
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java
index 4a9dd97..0605d9e 100644
--- a/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/DynamicSystemServiceTest.java
@@ -36,7 +36,7 @@
     public void test1() {
         assertTrue("dynamic_system service available", mService != null);
         try {
-            mService.startInstallation(1 << 20, 8 << 30);
+            mService.startInstallation("userdata", 8L << 30, false);
             fail("DynamicSystemService did not throw SecurityException as expected");
         } catch (SecurityException e) {
             // expected
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index 9180054..d70e164 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -207,14 +207,14 @@
     }
 
     @Test
-    public void serviceDisconnected_removeServiceAndAddToBinding() {
+    public void serviceDisconnected_removeServiceAndAddToCrashed() {
         when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
         mUserState.addServiceLocked(mMockConnection);
 
         mUserState.serviceDisconnectedLocked(mMockConnection);
 
         assertFalse(mUserState.getBoundServicesLocked().contains(mMockConnection));
-        assertTrue(mUserState.getBindingServicesLocked().contains(COMPONENT_NAME));
+        assertTrue(mUserState.getCrashedServicesLocked().contains(COMPONENT_NAME));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 29244f0..1edc953 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -34,9 +34,9 @@
 import static com.android.server.am.ActivityManagerInternalTest.CustomThread;
 import static com.android.server.am.ActivityManagerService.DISPATCH_UIDS_CHANGED_UI_MSG;
 import static com.android.server.am.ActivityManagerService.Injector;
-import static com.android.server.am.ActivityManagerService.NETWORK_STATE_BLOCK;
-import static com.android.server.am.ActivityManagerService.NETWORK_STATE_NO_CHANGE;
-import static com.android.server.am.ActivityManagerService.NETWORK_STATE_UNBLOCK;
+import static com.android.server.am.ProcessList.NETWORK_STATE_BLOCK;
+import static com.android.server.am.ProcessList.NETWORK_STATE_NO_CHANGE;
+import static com.android.server.am.ProcessList.NETWORK_STATE_UNBLOCK;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -274,7 +274,7 @@
 
         uidRec.setProcState = prevState;
         uidRec.setCurProcState(curState);
-        mAms.incrementProcStateSeqAndNotifyAppsLocked();
+        mAms.mProcessList.incrementProcStateSeqAndNotifyAppsLocked(mAms.mProcessList.mActiveUids);
 
         // @SuppressWarnings("GuardedBy")
         assertEquals(expectedGlobalCounter, mAms.mProcessList.mProcStateSeqCounter);
@@ -429,42 +429,42 @@
         uidRec.setCurProcState(PROCESS_STATE_RECEIVER);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Foreground to foreground
         uidRec.setProcState = PROCESS_STATE_FOREGROUND_SERVICE;
         uidRec.setCurProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Background to background
         uidRec.setProcState = PROCESS_STATE_CACHED_ACTIVITY;
         uidRec.setCurProcState(PROCESS_STATE_CACHED_EMPTY);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Background to background
         uidRec.setProcState = PROCESS_STATE_NONEXISTENT;
         uidRec.setCurProcState(PROCESS_STATE_CACHED_ACTIVITY);
         expectedBlockState = NETWORK_STATE_NO_CHANGE;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Background to foreground
         uidRec.setProcState = PROCESS_STATE_SERVICE;
         uidRec.setCurProcState(PROCESS_STATE_FOREGROUND_SERVICE);
         expectedBlockState = NETWORK_STATE_BLOCK;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
 
         // Foreground to background
         uidRec.setProcState = PROCESS_STATE_TOP;
         uidRec.setCurProcState(PROCESS_STATE_LAST_ACTIVITY);
         expectedBlockState = NETWORK_STATE_UNBLOCK;
         assertEquals(errorMsg.apply(expectedBlockState),
-                expectedBlockState, mAms.getBlockStateForUid(uidRec));
+                expectedBlockState, mAms.mProcessList.getBlockStateForUid(uidRec));
     }
 
     /**
@@ -473,8 +473,8 @@
      */
     @Test
     public void testDispatchUids_dispatchNeededChanges() throws RemoteException {
-        when(mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null))
-                .thenReturn(AppOpsManager.MODE_ALLOWED);
+        when(mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null,
+                null)).thenReturn(AppOpsManager.MODE_ALLOWED);
 
         final int[] changesToObserve = {
             ActivityManager.UID_OBSERVER_PROCSTATE,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 4aeeb0a..ec47a95 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -33,7 +33,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -43,17 +42,15 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.IBiometricAuthenticator;
 import android.hardware.biometrics.IBiometricService;
 import android.hardware.biometrics.IBiometricServiceReceiver;
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
-import android.hardware.face.FaceManager;
-import android.hardware.face.IFaceService;
 import android.hardware.fingerprint.FingerprintManager;
-import android.hardware.fingerprint.IFingerprintService;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.security.KeyStore;
 
 import androidx.test.InstrumentationRegistry;
@@ -68,8 +65,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.List;
-
 @SmallTest
 public class BiometricServiceTest {
 
@@ -98,71 +93,33 @@
     @Mock
     private PackageManager mPackageManager;
     @Mock
-    private AppOpsManager mAppOpsManager;
-    @Mock
     IBiometricServiceReceiver mReceiver1;
     @Mock
     IBiometricServiceReceiver mReceiver2;
     @Mock
-    FingerprintManager mFingerprintManager;
+    BiometricService.Injector mInjector;
     @Mock
-    FaceManager mFaceManager;
-
-    private static class MockInjector extends BiometricService.Injector {
-        @Override
-        IActivityManager getActivityManagerService() {
-            return mock(IActivityManager.class);
-        }
-
-        @Override
-        IStatusBarService getStatusBarService() {
-            return mock(IStatusBarService.class);
-        }
-
-        @Override
-        IFingerprintService getFingerprintService() {
-            return mock(IFingerprintService.class);
-        }
-
-        @Override
-        IFaceService getFaceService() {
-            return mock(IFaceService.class);
-        }
-
-        @Override
-        BiometricService.SettingObserver getSettingObserver(Context context, Handler handler,
-                List<BiometricService.EnabledOnKeyguardCallback> callbacks) {
-            return mock(BiometricService.SettingObserver.class);
-        }
-
-        @Override
-        KeyStore getKeyStore() {
-            return mock(KeyStore.class);
-        }
-
-        @Override
-        boolean isDebugEnabled(Context context, int userId) {
-            return false;
-        }
-
-        @Override
-        void publishBinderService(BiometricService service, IBiometricService.Stub impl) {
-            // no-op for test
-        }
-    }
+    IBiometricAuthenticator mFingerprintAuthenticator;
+    @Mock
+    IBiometricAuthenticator mFaceAuthenticator;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
-        when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
-        when(mContext.getSystemService(Context.FINGERPRINT_SERVICE))
-                .thenReturn(mFingerprintManager);
-        when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
         when(mContext.getResources()).thenReturn(mResources);
 
+        when(mInjector.getActivityManagerService()).thenReturn(mock(IActivityManager.class));
+        when(mInjector.getStatusBarService()).thenReturn(mock(IStatusBarService.class));
+        when(mInjector.getFingerprintAuthenticator()).thenReturn(mFingerprintAuthenticator);
+        when(mInjector.getFaceAuthenticator()).thenReturn(mFaceAuthenticator);
+        when(mInjector.getSettingObserver(any(), any(), any())).thenReturn(
+                mock(BiometricService.SettingObserver.class));
+        when(mInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
+        when(mInjector.isDebugEnabled(any(), anyInt())).thenReturn(false);
+
         when(mResources.getString(R.string.biometric_error_hw_unavailable))
                 .thenReturn(ERROR_HW_UNAVAILABLE);
         when(mResources.getString(R.string.biometric_not_recognized))
@@ -172,61 +129,69 @@
     }
 
     @Test
-    public void testAuthenticate_withoutHardware_returnsErrorHardwareNotPresent() throws Exception {
+    public void testAuthenticate_withoutHardware_returnsErrorHardwareNotPresent() throws
+            Exception {
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
                 .thenReturn(false);
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IRIS)).thenReturn(false);
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(false);
 
-        mBiometricService = new BiometricService(mContext, new MockInjector());
+        mBiometricService = new BiometricService(mContext, mInjector);
         mBiometricService.onStart();
 
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
                 false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
-                eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT), eq(ERROR_HW_UNAVAILABLE));
+                eq(BiometricAuthenticator.TYPE_NONE),
+                eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT),
+                eq(0 /* vendorCode */));
     }
 
     @Test
     public void testAuthenticate_withoutEnrolled_returnsErrorNoBiometrics() throws Exception {
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
-        when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+        when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
 
-        mBiometricService = new BiometricService(mContext, new MockInjector());
+        mBiometricService = new BiometricService(mContext, mInjector);
         mBiometricService.onStart();
 
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
                 false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
-                eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS), any());
+                eq(BiometricAuthenticator.TYPE_FINGERPRINT),
+                eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS),
+                eq(0 /* vendorCode */));
     }
 
     @Test
-    public void testAuthenticate_whenHalIsDead_returnsErrorHardwareUnavailable() throws Exception {
+    public void testAuthenticate_whenHalIsDead_returnsErrorHardwareUnavailable() throws
+            Exception {
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
-        when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
-        when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
+        when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
+        when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(false);
 
-        mBiometricService = new BiometricService(mContext, new MockInjector());
+        mBiometricService = new BiometricService(mContext, mInjector);
         mBiometricService.onStart();
 
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
                 false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
-                eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(ERROR_HW_UNAVAILABLE));
+                eq(BiometricAuthenticator.TYPE_NONE),
+                eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE),
+                eq(0 /* vendorCode */));
     }
 
     @Test
     public void testAuthenticateFace_respectsUserSetting()
             throws Exception {
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
-        when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
-        when(mFaceManager.isHardwareDetected()).thenReturn(true);
+        when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
+        when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
 
-        mBiometricService = new BiometricService(mContext, new MockInjector());
+        mBiometricService = new BiometricService(mContext, mInjector);
         mBiometricService.onStart();
 
         // Disabled in user settings receives onError
@@ -235,7 +200,9 @@
                 false /* allowDeviceCredential */);
         waitForIdle();
         verify(mReceiver1).onError(
-                eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(ERROR_HW_UNAVAILABLE));
+                eq(BiometricAuthenticator.TYPE_NONE),
+                eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE),
+                eq(0 /* vendorCode */));
 
         // Enrolled, not disabled in settings, user requires confirmation in settings
         resetReceiver();
@@ -245,8 +212,8 @@
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
                 false /* allowDeviceCredential */);
         waitForIdle();
-        verify(mReceiver1, never()).onError(anyInt(), any(String.class));
-        verify(mBiometricService.mFaceService).prepareForAuthentication(
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
+        verify(mBiometricService.mAuthenticators.get(0).impl).prepareForAuthentication(
                 eq(true) /* requireConfirmation */,
                 any(IBinder.class),
                 anyLong() /* sessionId */,
@@ -265,7 +232,7 @@
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
                 false /* allowDeviceCredential */);
         waitForIdle();
-        verify(mBiometricService.mFaceService).prepareForAuthentication(
+        verify(mBiometricService.mAuthenticators.get(0).impl).prepareForAuthentication(
                 eq(false) /* requireConfirmation */,
                 any(IBinder.class),
                 anyLong() /* sessionId */,
@@ -281,7 +248,7 @@
     @Test
     public void testAuthenticate_happyPathWithoutConfirmation() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
-        mBiometricService = new BiometricService(mContext, new MockInjector());
+        mBiometricService = new BiometricService(mContext, mInjector);
         mBiometricService.onStart();
 
         // Start testing the happy path
@@ -295,8 +262,9 @@
 
         // Invokes <Modality>Service#prepareForAuthentication
         ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
-        verify(mReceiver1, never()).onError(anyInt(), any(String.class));
-        verify(mBiometricService.mFingerprintService).prepareForAuthentication(
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
+        verify(mBiometricService.mAuthenticators.get(0).impl).prepareForAuthentication(
+                anyBoolean() /* requireConfirmation */,
                 any(IBinder.class),
                 anyLong() /* sessionId */,
                 anyInt() /* userId */,
@@ -316,7 +284,7 @@
                 BiometricService.STATE_AUTH_STARTED);
 
         // startPreparedClient invoked
-        verify(mBiometricService.mFingerprintService)
+        verify(mBiometricService.mAuthenticators.get(0).impl)
                 .startPreparedClient(cookieCaptor.getValue());
 
         // StatusBar showBiometricDialog invoked
@@ -337,8 +305,7 @@
         assertEquals(mBiometricService.mCurrentAuthSession.mState,
                 BiometricService.STATE_AUTHENTICATED_PENDING_SYSUI);
         // Notify SystemUI hardware authenticated
-        verify(mBiometricService.mStatusBarService).onBiometricAuthenticated(
-                eq(true) /* authenticated */, eq(null) /* failureReason */);
+        verify(mBiometricService.mStatusBarService).onBiometricAuthenticated();
 
         // SystemUI sends callback with dismissed reason
         mBiometricService.mInternalReceiver.onDialogDismissed(
@@ -355,7 +322,7 @@
     @Test
     public void testAuthenticate_noBiometrics_credentialAllowed() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
-        when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
+        when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
         invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
                 true /* requireConfirmation */, true /* allowDeviceCredential */);
         waitForIdle();
@@ -409,8 +376,10 @@
         mBiometricService.mInternalReceiver.onAuthenticationFailed();
         waitForIdle();
 
-        verify(mBiometricService.mStatusBarService)
-                .onBiometricAuthenticated(eq(false), eq(ERROR_NOT_RECOGNIZED));
+        verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricAuthenticator.TYPE_NONE),
+                eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED),
+                eq(0 /* vendorCode */));
         verify(mReceiver1).onAuthenticationFailed();
         assertEquals(mBiometricService.mCurrentAuthSession.mState,
                 BiometricService.STATE_AUTH_PAUSED);
@@ -426,15 +395,18 @@
         mBiometricService.mInternalReceiver.onAuthenticationFailed();
         waitForIdle();
 
-        verify(mBiometricService.mStatusBarService)
-                .onBiometricAuthenticated(eq(false), eq(ERROR_NOT_RECOGNIZED));
+        verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricAuthenticator.TYPE_NONE),
+                eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED),
+                eq(0 /* vendorCode */));
         verify(mReceiver1).onAuthenticationFailed();
         assertEquals(mBiometricService.mCurrentAuthSession.mState,
                 BiometricService.STATE_AUTH_STARTED);
     }
 
     @Test
-    public void testErrorCanceled_whenAuthenticating_notifiesSystemUIAndClient() throws Exception {
+    public void testErrorCanceled_whenAuthenticating_notifiesSystemUIAndClient() throws
+            Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
                 false /* requireConfirmation */, false /* allowDeviceCredential */);
@@ -451,15 +423,15 @@
                 BiometricService.STATE_AUTH_STARTED);
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
-                BiometricConstants.BIOMETRIC_ERROR_CANCELED, ERROR_CANCELED);
+                BiometricAuthenticator.TYPE_FINGERPRINT,
+                BiometricConstants.BIOMETRIC_ERROR_CANCELED, 0 /* vendorCode */);
         waitForIdle();
 
         // Auth session doesn't become null until SystemUI responds that the animation is completed
         assertNotNull(mBiometricService.mCurrentAuthSession);
         // ERROR_CANCELED is not sent until SystemUI responded that animation is completed
-        verify(mReceiver1, never()).onError(
-                anyInt(), anyString());
-        verify(mReceiver2, never()).onError(anyInt(), any(String.class));
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
+        verify(mReceiver2, never()).onError(anyInt(), anyInt(), anyInt());
 
         // SystemUI dialog closed
         verify(mBiometricService.mStatusBarService).hideAuthenticationDialog();
@@ -469,8 +441,9 @@
                 .onDialogDismissed(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED);
         waitForIdle();
         verify(mReceiver1).onError(
+                eq(BiometricAuthenticator.TYPE_FINGERPRINT),
                 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
-                eq(ERROR_CANCELED));
+                eq(0 /* vendorCode */));
         assertNull(mBiometricService.mCurrentAuthSession);
     }
 
@@ -482,14 +455,17 @@
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
-                ERROR_TIMEOUT);
+                0 /* vendorCode */);
         waitForIdle();
 
         assertEquals(mBiometricService.mCurrentAuthSession.mState,
                 BiometricService.STATE_AUTH_PAUSED);
-        verify(mBiometricService.mStatusBarService)
-                .onBiometricAuthenticated(eq(false), eq(ERROR_TIMEOUT));
+        verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricAuthenticator.TYPE_FACE),
+                eq(BiometricConstants.BIOMETRIC_ERROR_TIMEOUT),
+                eq(0 /* vendorCode */));
         // Timeout does not count as fail as per BiometricPrompt documentation.
         verify(mReceiver1, never()).onAuthenticationFailed();
 
@@ -524,22 +500,25 @@
     public void testErrorFromHal_whenPaused_notifiesSystemUIAndClient() throws Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
-                false /* requireCOnfirmation */, false /* allowDeviceCredential */);
+                false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
-                ERROR_TIMEOUT);
+                0 /* vendorCode */);
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
                 BiometricConstants.BIOMETRIC_ERROR_CANCELED,
-                ERROR_CANCELED);
+                0 /* vendorCode */);
         waitForIdle();
 
         // Client receives error immediately
         verify(mReceiver1).onError(
+                eq(BiometricAuthenticator.TYPE_FACE),
                 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
-                eq(ERROR_CANCELED));
+                eq(0 /* vendorCode */));
         // Dialog is hidden immediately
         verify(mBiometricService.mStatusBarService).hideAuthenticationDialog();
         // Auth session is over
@@ -558,26 +537,29 @@
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FINGERPRINT,
                 BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS,
-                ERROR_UNABLE_TO_PROCESS);
+                0 /* vendorCode */);
         waitForIdle();
 
         // Sends error to SystemUI and does not notify client yet
         assertEquals(mBiometricService.mCurrentAuthSession.mState,
                 BiometricService.STATE_ERROR_PENDING_SYSUI);
         verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricAuthenticator.TYPE_FINGERPRINT),
                 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
-                eq(ERROR_UNABLE_TO_PROCESS));
+                eq(0 /* vendorCode */));
         verify(mBiometricService.mStatusBarService, never()).hideAuthenticationDialog();
-        verify(mReceiver1, never()).onError(anyInt(), anyString());
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
 
         // SystemUI animation completed, client is notified, auth session is over
         mBiometricService.mInternalReceiver
                 .onDialogDismissed(BiometricPrompt.DISMISSED_REASON_ERROR);
         waitForIdle();
         verify(mReceiver1).onError(
+                eq(BiometricAuthenticator.TYPE_FINGERPRINT),
                 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
-                eq(ERROR_UNABLE_TO_PROCESS));
+                eq(0 /* vendorCode */));
         assertNull(mBiometricService.mCurrentAuthSession);
     }
 
@@ -590,8 +572,9 @@
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForPendingSession(mBiometricService.mPendingAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
-                ERROR_LOCKOUT);
+                0 /* vendorCode */);
         waitForIdle();
 
         // Pending auth session becomes current auth session, since device credential should
@@ -622,8 +605,9 @@
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForPendingSession(mBiometricService.mPendingAuthSession),
+                BiometricAuthenticator.TYPE_FINGERPRINT,
                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
-                ERROR_LOCKOUT);
+                0 /* vendorCode */);
         waitForIdle();
 
         // Error is sent to client
@@ -690,17 +674,18 @@
 
         assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
                 mBiometricService.mCurrentAuthSession.mState);
-        verify(mReceiver1, never()).onError(anyInt(), anyString());
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FINGERPRINT,
                 BiometricConstants.BIOMETRIC_ERROR_CANCELED,
-                ERROR_CANCELED);
+                0 /* vendorCode */);
         waitForIdle();
 
         assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
                 mBiometricService.mCurrentAuthSession.mState);
-        verify(mReceiver1, never()).onError(anyInt(), anyString());
+        verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
     }
 
     @Test
@@ -714,15 +699,17 @@
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FINGERPRINT,
                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
-                ERROR_LOCKOUT);
+                0 /* vendorCode */);
         waitForIdle();
 
         assertEquals(BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL,
                 mBiometricService.mCurrentAuthSession.mState);
         verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricAuthenticator.TYPE_FINGERPRINT),
                 eq(BiometricConstants.BIOMETRIC_ERROR_LOCKOUT),
-                eq(ERROR_LOCKOUT));
+                eq(0 /* vendorCode */));
     }
 
     @Test
@@ -736,15 +723,17 @@
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FINGERPRINT,
                 BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS,
-                ERROR_UNABLE_TO_PROCESS);
+                0 /* vendorCode */);
         waitForIdle();
 
         assertEquals(BiometricService.STATE_ERROR_PENDING_SYSUI,
                 mBiometricService.mCurrentAuthSession.mState);
         verify(mBiometricService.mStatusBarService).onBiometricError(
+                eq(BiometricAuthenticator.TYPE_FINGERPRINT),
                 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
-                eq(ERROR_UNABLE_TO_PROCESS));
+                eq(0 /* vendorCode */));
     }
 
     @Test
@@ -758,9 +747,10 @@
                 .onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
         waitForIdle();
         verify(mReceiver1).onError(
+                eq(BiometricAuthenticator.TYPE_FINGERPRINT),
                 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
-                eq(ERROR_USER_CANCELED));
-        verify(mBiometricService.mFingerprintService).cancelAuthenticationFromService(
+                eq(0 /* vendorCode */));
+        verify(mBiometricService.mAuthenticators.get(0).impl).cancelAuthenticationFromService(
                 any(),
                 any(),
                 anyInt(),
@@ -778,13 +768,15 @@
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
-                ERROR_TIMEOUT);
+                0 /* vendorCode */);
         mBiometricService.mInternalReceiver.onDialogDismissed(
                 BiometricPrompt.DISMISSED_REASON_NEGATIVE);
         waitForIdle();
 
-        verify(mBiometricService.mFaceService, never()).cancelAuthenticationFromService(
+        verify(mBiometricService.mAuthenticators.get(0).impl,
+                never()).cancelAuthenticationFromService(
                 any(),
                 any(),
                 anyInt(),
@@ -794,20 +786,23 @@
     }
 
     @Test
-    public void testDismissedReasonUserCancel_whilePaused_doesntInvokeHalCancel() throws Exception {
+    public void testDismissedReasonUserCancel_whilePaused_doesntInvokeHalCancel() throws
+            Exception {
         setupAuthForOnly(BiometricAuthenticator.TYPE_FACE);
         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
                 false /* requireConfirmation */, false /* allowDeviceCredential */);
 
         mBiometricService.mInternalReceiver.onError(
                 getCookieForCurrentSession(mBiometricService.mCurrentAuthSession),
+                BiometricAuthenticator.TYPE_FACE,
                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
-                ERROR_TIMEOUT);
+                0 /* vendorCode */);
         mBiometricService.mInternalReceiver.onDialogDismissed(
                 BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
         waitForIdle();
 
-        verify(mBiometricService.mFaceService, never()).cancelAuthenticationFromService(
+        verify(mBiometricService.mAuthenticators.get(0).impl,
+                never()).cancelAuthenticationFromService(
                 any(),
                 any(),
                 anyInt(),
@@ -830,7 +825,8 @@
         waitForIdle();
 
         // doesn't send cancel to HAL
-        verify(mBiometricService.mFaceService, never()).cancelAuthenticationFromService(
+        verify(mBiometricService.mAuthenticators.get(0).impl,
+                never()).cancelAuthenticationFromService(
                 any(),
                 any(),
                 anyInt(),
@@ -838,8 +834,9 @@
                 anyInt(),
                 anyBoolean());
         verify(mReceiver1).onError(
+                eq(BiometricAuthenticator.TYPE_FACE),
                 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
-                eq(ERROR_USER_CANCELED));
+                eq(0 /* vendorCode */));
         assertNull(mBiometricService.mCurrentAuthSession);
     }
 
@@ -863,7 +860,7 @@
 
     // Helper methods
 
-    private void setupAuthForOnly(int modality) {
+    private void setupAuthForOnly(int modality) throws RemoteException {
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
                 .thenReturn(false);
         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(false);
@@ -871,17 +868,17 @@
         if (modality == BiometricAuthenticator.TYPE_FINGERPRINT) {
             when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
                     .thenReturn(true);
-            when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
-            when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
+            when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
+            when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
         } else if (modality == BiometricAuthenticator.TYPE_FACE) {
             when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
-            when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
-            when(mFaceManager.isHardwareDetected()).thenReturn(true);
+            when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
+            when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
         } else {
             fail("Unknown modality: " + modality);
         }
 
-        mBiometricService = new BiometricService(mContext, new MockInjector());
+        mBiometricService = new BiometricService(mContext, mInjector);
         mBiometricService.onStart();
 
         when(mBiometricService.mSettingObserver.getFaceEnabledForApps(anyInt())).thenReturn(true);
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 537287d..9863057 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -52,6 +52,7 @@
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockSettingsInternal;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.server.LocalServices;
 import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
 import com.android.server.wm.WindowManagerInternal;
@@ -104,6 +105,7 @@
     FaceManager mFaceManager;
     PackageManager mPackageManager;
     protected boolean mHasSecureLockScreen;
+    FakeSettings mSettings;
 
     @Override
     protected void setUp() throws Exception {
@@ -125,6 +127,7 @@
         mFingerprintManager = mock(FingerprintManager.class);
         mFaceManager = mock(FaceManager.class);
         mPackageManager = mock(PackageManager.class);
+        mSettings = new FakeSettings();
 
         LocalServices.removeServiceForTest(LockSettingsInternal.class);
         LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
@@ -162,7 +165,7 @@
         mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage,
                 mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager,
                 mSpManager, mAuthSecretService, mGsiService, mRecoverableKeyStoreManager,
-                mUserManagerInternal, mDeviceStateCache);
+                mUserManagerInternal, mDeviceStateCache, mSettings);
         when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO);
         mPrimaryUserProfiles.add(PRIMARY_USER_INFO);
         installChildProfile(MANAGED_PROFILE_USER_ID);
@@ -195,6 +198,7 @@
         mockBiometricsHardwareFingerprintsAndTemplates(PRIMARY_USER_ID);
         mockBiometricsHardwareFingerprintsAndTemplates(MANAGED_PROFILE_USER_ID);
 
+        mSettings.setDeviceProvisioned(true);
         mLocalService = LocalServices.getService(LockSettingsInternal.class);
     }
 
@@ -307,4 +311,22 @@
     protected static void assertArrayNotEquals(byte[] expected, byte[] actual) {
         assertFalse(Arrays.equals(expected, actual));
     }
+
+    protected LockscreenCredential newPassword(String password) {
+        return LockscreenCredential.createPasswordOrNone(password);
+    }
+
+    protected LockscreenCredential newPin(String pin) {
+        return LockscreenCredential.createPinOrNone(pin);
+    }
+
+    protected LockscreenCredential newPattern(String pattern) {
+        return LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(
+                pattern.getBytes()));
+    }
+
+    protected LockscreenCredential nonePassword() {
+        return LockscreenCredential.createNone();
+    }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
index d2a9145..5c54883 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
@@ -15,9 +15,6 @@
  */
 package com.android.server.locksettings;
 
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-
 import static com.android.server.testutils.TestUtils.assertExpectException;
 
 import static org.mockito.Mockito.anyInt;
@@ -30,7 +27,7 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
 
 import org.mockito.ArgumentCaptor;
@@ -59,56 +56,53 @@
     }
 
     public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException {
-        final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
-        final byte[] newPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
+        final LockscreenCredential password = newPassword("password");
+        final LockscreenCredential newPassword = newPassword("newpassword");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // clear password
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, null,
-                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, true);
+        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, true);
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // set a new password
-        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
+                false);
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                newPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
     public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException {
-        final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
-        final byte[] newPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
+        final LockscreenCredential password = newPassword("password");
+        final LockscreenCredential newPassword = newPassword("newpassword");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // Untrusted change password
-        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true);
+        mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
+                true);
         assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // Verify the password
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode());
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                newPassword, 0, PRIMARY_USER_ID).getResponseCode());
     }
 
     public void testUntrustedCredentialChangeMaintainsAuthSecret() throws RemoteException {
-        final byte[] password =
-                "testUntrustedCredentialChangeMaintainsAuthSecret-password".getBytes();
-        final byte[] newPassword =
-                "testUntrustedCredentialChangeMaintainsAuthSecret-newpassword".getBytes();
+        final LockscreenCredential password = newPassword("password");
+        final LockscreenCredential newPassword = newPassword("newpassword");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         // Untrusted change password
-        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true);
+        mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
+                true);
 
         // Verify the password
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(newPassword,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                newPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
 
         // Ensure the same secret was passed each time
@@ -118,31 +112,30 @@
     }
 
     public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException {
-        final byte[] password =
-                "testUntrustedCredentialChangeBlockedIfSpNotCached-password".getBytes();
-        final byte[] newPassword =
-                "testUntrustedCredentialChangeBlockedIfSpNotCached-newpassword".getBytes();
+        final LockscreenCredential password = newPassword("password");
+        final LockscreenCredential newPassword = newPassword("newpassword");
 
         // Disable caching for this test
         enableSpCaching(false);
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
+        flushHandlerTasks();
+
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // Untrusted change password
         assertExpectException(
                 IllegalStateException.class,
                 /* messageRegex= */ "Untrusted credential reset not possible without cached SP",
-                () -> mService.setLockCredential(newPassword,
-                        LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                        PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, true));
+                () -> mService.setLockCredential(newPassword, nonePassword(),
+                        PRIMARY_USER_ID, true));
         assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // Verify the new password doesn't work but the old one still does
-        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(newPassword,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
+                newPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                password, 0, PRIMARY_USER_ID)
                         .getResponseCode());
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
new file mode 100644
index 0000000..70a927c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
@@ -0,0 +1,36 @@
+/*
+ * 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.locksettings;
+
+import android.provider.Settings;
+
+public class FakeSettings {
+
+    private int mDeviceProvisioned;
+
+    public void setDeviceProvisioned(boolean provisioned) {
+        mDeviceProvisioned = provisioned ? 1 : 0;
+    }
+
+    public int globalGetInt(String keyName) {
+        switch (keyName) {
+            case Settings.Global.DEVICE_PROVISIONED:
+                return mDeviceProvisioned;
+            default:
+                throw new IllegalArgumentException("Unhandled global settings: " + keyName);
+        }
+    }
+}
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 fcd98e0..7e7e170 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -20,9 +20,11 @@
 
 import android.app.IActivityManager;
 import android.app.admin.DeviceStateCache;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.hardware.authsecret.V1_0.IAuthSecret;
 import android.os.Handler;
+import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserManagerInternal;
@@ -31,6 +33,7 @@
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.server.ServiceThread;
 import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
 
@@ -50,12 +53,14 @@
         private RecoverableKeyStoreManager mRecoverableKeyStoreManager;
         private UserManagerInternal mUserManagerInternal;
         private DeviceStateCache mDeviceStateCache;
+        private FakeSettings mSettings;
 
         public MockInjector(Context context, LockSettingsStorage storage, KeyStore keyStore,
                 IActivityManager activityManager, LockPatternUtils lockPatternUtils,
                 IStorageManager storageManager, SyntheticPasswordManager spManager,
                 FakeGsiService gsiService, RecoverableKeyStoreManager recoverableKeyStoreManager,
-                UserManagerInternal userManagerInternal, DeviceStateCache deviceStateCache) {
+                UserManagerInternal userManagerInternal, DeviceStateCache deviceStateCache,
+                FakeSettings settings) {
             super(context);
             mLockSettingsStorage = storage;
             mKeyStore = keyStore;
@@ -67,6 +72,7 @@
             mRecoverableKeyStoreManager = recoverableKeyStoreManager;
             mUserManagerInternal = userManagerInternal;
             mDeviceStateCache = deviceStateCache;
+            mSettings = settings;
         }
 
         @Override
@@ -119,6 +125,12 @@
         }
 
         @Override
+        public int settingsGlobalGetInt(ContentResolver contentResolver, String keyName,
+                int defaultValue) {
+            return mSettings.globalGetInt(keyName);
+        }
+
+        @Override
         public UserManagerInternal getUserManagerInternal() {
             return mUserManagerInternal;
         }
@@ -144,27 +156,33 @@
         }
     }
 
+    public MockInjector mInjector;
+
     protected LockSettingsServiceTestable(Context context, LockPatternUtils lockPatternUtils,
             LockSettingsStorage storage, FakeGateKeeperService gatekeeper, KeyStore keystore,
             IStorageManager storageManager, IActivityManager mActivityManager,
             SyntheticPasswordManager spManager, IAuthSecret authSecretService,
             FakeGsiService gsiService, RecoverableKeyStoreManager recoverableKeyStoreManager,
-            UserManagerInternal userManagerInternal, DeviceStateCache deviceStateCache) {
+            UserManagerInternal userManagerInternal, DeviceStateCache deviceStateCache,
+            FakeSettings settings) {
         super(new MockInjector(context, storage, keystore, mActivityManager, lockPatternUtils,
                 storageManager, spManager, gsiService,
-                recoverableKeyStoreManager, userManagerInternal, deviceStateCache));
+                recoverableKeyStoreManager, userManagerInternal, deviceStateCache, settings));
         mGateKeeperService = gatekeeper;
         mAuthSecretService = authSecretService;
     }
 
     @Override
-    protected void tieProfileLockToParent(int userId, byte[] password) {
-        mStorage.writeChildProfileLock(userId, password);
+    protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
+        Parcel parcel = Parcel.obtain();
+        parcel.writeParcelable(password, 0);
+        mStorage.writeChildProfileLock(userId, parcel.marshall());
+        parcel.recycle();
     }
 
     @Override
-    protected byte[] getDecryptedPasswordForTiedProfile(int userId) throws FileNotFoundException,
-            KeyPermanentlyInvalidatedException {
+    protected LockscreenCredential getDecryptedPasswordForTiedProfile(int userId)
+            throws FileNotFoundException, KeyPermanentlyInvalidatedException {
         byte[] storedData = mStorage.readChildProfileLock(userId);
         if (storedData == null) {
             throw new FileNotFoundException("Child profile lock file not found");
@@ -176,6 +194,13 @@
         } catch (RemoteException e) {
             // shouldn't happen.
         }
-        return storedData;
+        Parcel parcel = Parcel.obtain();
+        try {
+            parcel.unmarshall(storedData, 0, storedData.length);
+            parcel.setDataPosition(0);
+            return (LockscreenCredential) parcel.readParcelable(null);
+        } finally {
+            parcel.recycle();
+        }
     }
 }
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 5818133..86ef31a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -16,14 +16,10 @@
 
 package com.android.server.locksettings;
 
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -39,6 +35,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.locksettings.FakeGateKeeperService.VerifyHandle;
 import com.android.server.locksettings.LockSettingsStorage.CredentialHash;
@@ -61,60 +58,51 @@
     }
 
     public void testCreatePasswordPrimaryUser() throws RemoteException {
-        testCreateCredential(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD,
-                PASSWORD_QUALITY_ALPHABETIC);
+        testCreateCredential(PRIMARY_USER_ID, newPassword("password"));
     }
 
     public void testCreatePasswordFailsWithoutLockScreen() throws RemoteException {
-        testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "password",
-                CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC);
+        testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, newPassword("password"));
     }
 
     public void testCreatePatternPrimaryUser() throws RemoteException {
-        testCreateCredential(PRIMARY_USER_ID, "123456789", CREDENTIAL_TYPE_PATTERN,
-                PASSWORD_QUALITY_SOMETHING);
+        testCreateCredential(PRIMARY_USER_ID, newPattern("123456789"));
     }
 
     public void testCreatePatternFailsWithoutLockScreen() throws RemoteException {
-        testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, "123456789",
-                CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING);
+        testCreateCredentialFailsWithoutLockScreen(PRIMARY_USER_ID, newPattern("123456789"));
     }
 
     public void testChangePasswordPrimaryUser() throws RemoteException {
-        testChangeCredentials(PRIMARY_USER_ID, "78963214", CREDENTIAL_TYPE_PATTERN,
-                "asdfghjk", CREDENTIAL_TYPE_PASSWORD, PASSWORD_QUALITY_ALPHABETIC);
+        testChangeCredentials(PRIMARY_USER_ID, newPattern("78963214"), newPassword("asdfghjk"));
     }
 
     public void testChangePatternPrimaryUser() throws RemoteException {
-        testChangeCredentials(PRIMARY_USER_ID, "!£$%^&*(())", CREDENTIAL_TYPE_PASSWORD,
-                "1596321", CREDENTIAL_TYPE_PATTERN, PASSWORD_QUALITY_SOMETHING);
+        testChangeCredentials(PRIMARY_USER_ID, newPassword("!£$%^&*(())"), newPattern("1596321"));
     }
 
     public void testChangePasswordFailPrimaryUser() throws RemoteException {
         final long sid = 1234;
-        initializeStorageWithCredential(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid);
+        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), sid);
 
-        assertFalse(mService.setLockCredential("newpwd".getBytes(), CREDENTIAL_TYPE_PASSWORD,
-                    "badpwd".getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false));
-        assertVerifyCredentials(PRIMARY_USER_ID, "password", CREDENTIAL_TYPE_PASSWORD, sid);
+        assertFalse(mService.setLockCredential(newPassword("newpwd"), newPassword("badpwd"),
+                    PRIMARY_USER_ID, false));
+        assertVerifyCredentials(PRIMARY_USER_ID, newPassword("password"), sid);
     }
 
     public void testClearPasswordPrimaryUser() throws RemoteException {
-        final String PASSWORD = "password";
-        initializeStorageWithCredential(PRIMARY_USER_ID, PASSWORD, CREDENTIAL_TYPE_PASSWORD, 1234);
-        assertTrue(mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, PASSWORD.getBytes(),
-                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false));
-        assertFalse(mService.havePassword(PRIMARY_USER_ID));
-        assertFalse(mService.havePattern(PRIMARY_USER_ID));
+        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), 1234);
+        assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
+                PRIMARY_USER_ID, false));
+        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
     public void testManagedProfileUnifiedChallenge() throws RemoteException {
-        final String firstUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-1";
-        final String secondUnifiedPassword = "testManagedProfileUnifiedChallenge-pwd-2";
-        assertTrue(mService.setLockCredential(firstUnifiedPassword.getBytes(),
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                null, PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false));
+        final LockscreenCredential firstUnifiedPassword = newPassword("pwd-1");
+        final LockscreenCredential secondUnifiedPassword = newPassword("pwd-2");
+        assertTrue(mService.setLockCredential(firstUnifiedPassword,
+                nonePassword(), PRIMARY_USER_ID, false));
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
         final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
@@ -132,8 +120,8 @@
         mGateKeeperService.clearAuthToken(TURNED_OFF_PROFILE_USER_ID);
         // verify credential
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                firstUnifiedPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
-                PRIMARY_USER_ID).getResponseCode());
+                firstUnifiedPassword, 0, PRIMARY_USER_ID)
+                .getResponseCode());
 
         // Verify that we have a new auth token for the profile
         assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
@@ -148,16 +136,15 @@
          */
         mStorageManager.setIgnoreBadUnlock(true);
         // Change primary password and verify that profile SID remains
-        assertTrue(mService.setLockCredential(secondUnifiedPassword.getBytes(),
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, firstUnifiedPassword.getBytes(),
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false));
+        assertTrue(mService.setLockCredential(
+                secondUnifiedPassword, firstUnifiedPassword, PRIMARY_USER_ID, false));
         mStorageManager.setIgnoreBadUnlock(false);
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
         assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
 
         // Clear unified challenge
-        assertTrue(mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
-                secondUnifiedPassword.getBytes(), PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID,
+        assertTrue(mService.setLockCredential(nonePassword(),
+                secondUnifiedPassword, PRIMARY_USER_ID,
                 false));
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
@@ -165,19 +152,19 @@
     }
 
     public void testManagedProfileSeparateChallenge() throws RemoteException {
-        final String primaryPassword = "testManagedProfileSeparateChallenge-primary";
-        final String profilePassword = "testManagedProfileSeparateChallenge-profile";
-        assertTrue(mService.setLockCredential(primaryPassword.getBytes(),
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_COMPLEX, PRIMARY_USER_ID, false));
+        final LockscreenCredential primaryPassword = newPassword("primary");
+        final LockscreenCredential profilePassword = newPassword("profile");
+        assertTrue(mService.setLockCredential(primaryPassword,
+                nonePassword(),
+                PRIMARY_USER_ID, false));
         /* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new
          * credential as part of verifyCredential() before the new credential is committed in
          * StorageManager. So we relax the check in our mock StorageManager to allow that.
          */
         mStorageManager.setIgnoreBadUnlock(true);
-        assertTrue(mService.setLockCredential(profilePassword.getBytes(),
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_COMPLEX, MANAGED_PROFILE_USER_ID, false));
+        assertTrue(mService.setLockCredential(profilePassword,
+                nonePassword(),
+                MANAGED_PROFILE_USER_ID, false));
         mStorageManager.setIgnoreBadUnlock(false);
 
         final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
@@ -190,81 +177,69 @@
         mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID);
         // verify primary credential
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                primaryPassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
-                PRIMARY_USER_ID).getResponseCode());
+                primaryPassword, 0, PRIMARY_USER_ID)
+                .getResponseCode());
         assertNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
 
         // verify profile credential
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
-                MANAGED_PROFILE_USER_ID).getResponseCode());
+                profilePassword, 0, MANAGED_PROFILE_USER_ID)
+                .getResponseCode());
         assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
 
         // Change primary credential and make sure we don't affect profile
         mStorageManager.setIgnoreBadUnlock(true);
-        assertTrue(mService.setLockCredential("pwd".getBytes(),
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                primaryPassword.getBytes(), PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false));
+        assertTrue(mService.setLockCredential(
+                newPassword("pwd"), primaryPassword, PRIMARY_USER_ID, false));
         mStorageManager.setIgnoreBadUnlock(false);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword.getBytes(), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
-                MANAGED_PROFILE_USER_ID).getResponseCode());
+                profilePassword, 0, MANAGED_PROFILE_USER_ID)
+                .getResponseCode());
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
     }
 
     public void testSetLockCredential_forPrimaryUser_sendsCredentials() throws Exception {
-        final byte[] password = "password".getBytes();
-
         assertTrue(mService.setLockCredential(
-                password,
-                CREDENTIAL_TYPE_PASSWORD,
-                null,
-                PASSWORD_QUALITY_ALPHABETIC,
+                newPassword("password"),
+                nonePassword(),
                 PRIMARY_USER_ID,
                 false));
 
         verify(mRecoverableKeyStoreManager)
-                .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, password, PRIMARY_USER_ID);
+                .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "password".getBytes(),
+                        PRIMARY_USER_ID);
     }
 
     public void testSetLockCredential_forProfileWithSeparateChallenge_sendsCredentials()
             throws Exception {
-        final byte[] pattern = "12345".getBytes();
-
         assertTrue(mService.setLockCredential(
-                pattern,
-                CREDENTIAL_TYPE_PATTERN,
-                null,
-                PASSWORD_QUALITY_SOMETHING,
+                newPattern("12345"),
+                nonePassword(),
                 MANAGED_PROFILE_USER_ID,
                 false));
 
         verify(mRecoverableKeyStoreManager)
-                .lockScreenSecretChanged(CREDENTIAL_TYPE_PATTERN, pattern, MANAGED_PROFILE_USER_ID);
+                .lockScreenSecretChanged(CREDENTIAL_TYPE_PATTERN, "12345".getBytes(),
+                        MANAGED_PROFILE_USER_ID);
     }
 
     public void testSetLockCredential_forProfileWithSeparateChallenge_updatesCredentials()
             throws Exception {
-        final String oldCredential = "12345";
-        final byte[] newCredential = "newPassword".getBytes();
         initializeStorageWithCredential(
                 MANAGED_PROFILE_USER_ID,
-                oldCredential,
-                CREDENTIAL_TYPE_PATTERN,
-                PASSWORD_QUALITY_SOMETHING);
+                newPattern("12345"),
+                1234);
 
         assertTrue(mService.setLockCredential(
-                newCredential,
-                CREDENTIAL_TYPE_PASSWORD,
-                oldCredential.getBytes(),
-                PASSWORD_QUALITY_ALPHABETIC,
+                newPassword("newPassword"),
+                newPattern("12345"),
                 MANAGED_PROFILE_USER_ID,
                 false));
 
         verify(mRecoverableKeyStoreManager)
-                .lockScreenSecretChanged(
-                        CREDENTIAL_TYPE_PASSWORD, newCredential, MANAGED_PROFILE_USER_ID);
+                .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "newPassword".getBytes(),
+                        MANAGED_PROFILE_USER_ID);
     }
 
     public void testSetLockCredential_forProfileWithUnifiedChallenge_doesNotSendRandomCredential()
@@ -272,10 +247,8 @@
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
 
         assertTrue(mService.setLockCredential(
-                "12345".getBytes(),
-                CREDENTIAL_TYPE_PATTERN,
-                null,
-                PASSWORD_QUALITY_SOMETHING,
+                newPattern("12345"),
+                nonePassword(),
                 PRIMARY_USER_ID,
                 false));
 
@@ -287,40 +260,35 @@
     public void
             testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_updatesBothCredentials()
                     throws Exception {
-        final String oldCredential = "oldPassword";
-        final byte[] newCredential = "newPassword".getBytes();
+        final LockscreenCredential oldCredential = newPassword("oldPassword");
+        final LockscreenCredential newCredential = newPassword("newPassword");
         initializeStorageWithCredential(
-                PRIMARY_USER_ID, oldCredential, CREDENTIAL_TYPE_PASSWORD, 1234);
+                PRIMARY_USER_ID, oldCredential, 1234);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
 
         assertTrue(mService.setLockCredential(
                 newCredential,
-                CREDENTIAL_TYPE_PASSWORD,
-                oldCredential.getBytes(),
-                PASSWORD_QUALITY_ALPHABETIC,
+                oldCredential,
                 PRIMARY_USER_ID,
                 false));
 
         verify(mRecoverableKeyStoreManager)
-                .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential, PRIMARY_USER_ID);
+                .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential.getCredential(),
+                        PRIMARY_USER_ID);
         verify(mRecoverableKeyStoreManager)
-                .lockScreenSecretChanged(
-                        CREDENTIAL_TYPE_PASSWORD, newCredential, MANAGED_PROFILE_USER_ID);
+                .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential.getCredential(),
+                        MANAGED_PROFILE_USER_ID);
     }
 
     public void
             testSetLockCredential_forPrimaryUserWithUnifiedChallengeProfile_removesBothCredentials()
                     throws Exception {
-        final String oldCredential = "oldPassword";
-        initializeStorageWithCredential(
-                PRIMARY_USER_ID, oldCredential, CREDENTIAL_TYPE_PASSWORD, 1234);
+        initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("oldPassword"), 1234);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
 
         assertTrue(mService.setLockCredential(
-                null,
-                CREDENTIAL_TYPE_NONE,
-                oldCredential.getBytes(),
-                PASSWORD_QUALITY_UNSPECIFIED,
+                nonePassword(),
+                newPassword("oldPassword"),
                 PRIMARY_USER_ID,
                 false));
 
@@ -331,17 +299,13 @@
     }
 
     public void testSetLockCredential_nullCredential_removeBiometrics() throws RemoteException {
-        final String oldCredential = "oldPassword";
-
         initializeStorageWithCredential(
                 PRIMARY_USER_ID,
-                oldCredential,
-                CREDENTIAL_TYPE_PATTERN,
-                PASSWORD_QUALITY_SOMETHING);
+                newPattern("123654"),
+                1234);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
 
-        mService.setLockCredential(null, CREDENTIAL_TYPE_NONE, oldCredential.getBytes(),
-                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
+        mService.setLockCredential(nonePassword(), newPattern("123654"), PRIMARY_USER_ID, false);
 
         // Verify fingerprint is removed
         verify(mFingerprintManager).remove(any(), eq(PRIMARY_USER_ID), any());
@@ -353,41 +317,33 @@
 
     public void testSetLockCredential_forUnifiedToSeparateChallengeProfile_sendsNewCredentials()
             throws Exception {
-        final String parentPassword = "parentPassword";
-        final byte[] profilePassword = "profilePassword".getBytes();
-        initializeStorageWithCredential(
-                PRIMARY_USER_ID, parentPassword, CREDENTIAL_TYPE_PASSWORD, 1234);
+        final LockscreenCredential parentPassword = newPassword("parentPassword");
+        final LockscreenCredential profilePassword = newPassword("profilePassword");
+        initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword, 1234);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
 
         assertTrue(mService.setLockCredential(
                 profilePassword,
-                CREDENTIAL_TYPE_PASSWORD,
-                null,
-                PASSWORD_QUALITY_ALPHABETIC,
+                nonePassword(),
                 MANAGED_PROFILE_USER_ID,
                 false));
 
         verify(mRecoverableKeyStoreManager)
-                .lockScreenSecretChanged(
-                        CREDENTIAL_TYPE_PASSWORD, profilePassword, MANAGED_PROFILE_USER_ID);
+                .lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, profilePassword.getCredential(),
+                        MANAGED_PROFILE_USER_ID);
     }
 
     public void
             testSetLockCredential_forSeparateToUnifiedChallengeProfile_doesNotSendRandomCredential()
                     throws Exception {
-        final String parentPassword = "parentPassword";
-        final String profilePassword = "12345";
-        initializeStorageWithCredential(
-                PRIMARY_USER_ID, parentPassword, CREDENTIAL_TYPE_PASSWORD, 1234);
+        final LockscreenCredential parentPassword = newPassword("parentPassword");
+        final LockscreenCredential profilePassword = newPattern("12345");
+        initializeStorageWithCredential(PRIMARY_USER_ID, parentPassword, 1234);
         // Create and verify separate profile credentials.
-        testCreateCredential(
-                MANAGED_PROFILE_USER_ID,
-                profilePassword,
-                CREDENTIAL_TYPE_PATTERN,
-                PASSWORD_QUALITY_SOMETHING);
+        testCreateCredential(MANAGED_PROFILE_USER_ID, profilePassword);
 
         mService.setSeparateProfileChallengeEnabled(
-                MANAGED_PROFILE_USER_ID, false, profilePassword.getBytes());
+                MANAGED_PROFILE_USER_ID, false, profilePassword);
 
         // Called once for setting the initial separate profile credentials and not again during
         // unification.
@@ -396,132 +352,121 @@
     }
 
     public void testVerifyCredential_forPrimaryUser_sendsCredentials() throws Exception {
-        final String password = "password";
-        initializeStorageWithCredential(PRIMARY_USER_ID, password, CREDENTIAL_TYPE_PASSWORD, 1234);
+        final LockscreenCredential password = newPassword("password");
+        initializeStorageWithCredential(PRIMARY_USER_ID, password, 1234);
         reset(mRecoverableKeyStoreManager);
 
-        mService.verifyCredential(
-                password.getBytes(), CREDENTIAL_TYPE_PASSWORD, 1, PRIMARY_USER_ID);
+        mService.verifyCredential(password, 1, PRIMARY_USER_ID);
 
         verify(mRecoverableKeyStoreManager)
                 .lockScreenSecretAvailable(
-                        CREDENTIAL_TYPE_PASSWORD, password.getBytes(), PRIMARY_USER_ID);
+                        CREDENTIAL_TYPE_PASSWORD, password.getCredential(), PRIMARY_USER_ID);
     }
 
     public void testVerifyCredential_forProfileWithSeparateChallenge_sendsCredentials()
             throws Exception {
-        final byte[] pattern = "12345".getBytes();
+        final LockscreenCredential pattern = newPattern("12345");
         assertTrue(mService.setLockCredential(
                 pattern,
-                CREDENTIAL_TYPE_PATTERN,
-                null,
-                PASSWORD_QUALITY_SOMETHING,
+                nonePassword(),
                 MANAGED_PROFILE_USER_ID,
                 false));
         reset(mRecoverableKeyStoreManager);
 
-        mService.verifyCredential(pattern, CREDENTIAL_TYPE_PATTERN, 1, MANAGED_PROFILE_USER_ID);
+        mService.verifyCredential(pattern, 1, MANAGED_PROFILE_USER_ID);
 
         verify(mRecoverableKeyStoreManager)
                 .lockScreenSecretAvailable(
-                        CREDENTIAL_TYPE_PATTERN, pattern, MANAGED_PROFILE_USER_ID);
+                        CREDENTIAL_TYPE_PATTERN, pattern.getCredential(), MANAGED_PROFILE_USER_ID);
     }
 
     public void
             testVerifyCredential_forPrimaryUserWithUnifiedChallengeProfile_sendsCredentialsForBoth()
                     throws Exception {
-        final String pattern = "12345";
-        initializeStorageWithCredential(PRIMARY_USER_ID, pattern, CREDENTIAL_TYPE_PATTERN, 1234);
+        final LockscreenCredential pattern = newPattern("12345");
+        initializeStorageWithCredential(PRIMARY_USER_ID, pattern, 1234);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
         reset(mRecoverableKeyStoreManager);
 
-        mService.verifyCredential(pattern.getBytes(), CREDENTIAL_TYPE_PATTERN, 1, PRIMARY_USER_ID);
+        mService.verifyCredential(pattern, 1, PRIMARY_USER_ID);
 
         // Parent sends its credentials for both the parent and profile.
         verify(mRecoverableKeyStoreManager)
                 .lockScreenSecretAvailable(
-                        CREDENTIAL_TYPE_PATTERN, pattern.getBytes(), PRIMARY_USER_ID);
+                        CREDENTIAL_TYPE_PATTERN, pattern.getCredential(), PRIMARY_USER_ID);
         verify(mRecoverableKeyStoreManager)
                 .lockScreenSecretAvailable(
-                        CREDENTIAL_TYPE_PATTERN, pattern.getBytes(), MANAGED_PROFILE_USER_ID);
+                        CREDENTIAL_TYPE_PATTERN, pattern.getCredential(), MANAGED_PROFILE_USER_ID);
         // Profile doesn't send its own random credentials.
         verify(mRecoverableKeyStoreManager, never())
                 .lockScreenSecretAvailable(
                         eq(CREDENTIAL_TYPE_PASSWORD), any(), eq(MANAGED_PROFILE_USER_ID));
     }
 
-    private void testCreateCredential(int userId, String credential, int type, int quality)
+    private void testCreateCredential(int userId, LockscreenCredential credential)
             throws RemoteException {
-        assertTrue(mService.setLockCredential(credential.getBytes(), type, null, quality,
-                userId, false));
-        assertVerifyCredentials(userId, credential, type, -1);
+        assertTrue(mService.setLockCredential(credential, nonePassword(), userId, false));
+        assertVerifyCredentials(userId, credential, -1);
     }
 
     private void testCreateCredentialFailsWithoutLockScreen(
-            int userId, String credential, int type, int quality) throws RemoteException {
+            int userId, LockscreenCredential credential) throws RemoteException {
         mHasSecureLockScreen = false;
 
         try {
-            mService.setLockCredential(credential.getBytes(), type, null, quality,
-                    userId, false);
+            mService.setLockCredential(credential, null, userId, false);
             fail("An exception should have been thrown.");
         } catch (UnsupportedOperationException e) {
             // Success - the exception was expected.
         }
 
-        assertFalse(mService.havePassword(userId));
-        assertFalse(mService.havePattern(userId));
+        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(userId));
     }
 
-    private void testChangeCredentials(int userId, String newCredential, int newType,
-            String oldCredential, int oldType, int quality) throws RemoteException {
+    private void testChangeCredentials(int userId, LockscreenCredential newCredential,
+            LockscreenCredential oldCredential) throws RemoteException {
         final long sid = 1234;
-        initializeStorageWithCredential(userId, oldCredential, oldType, sid);
-        assertTrue(mService.setLockCredential(newCredential.getBytes(), newType,
-                oldCredential.getBytes(), quality, userId, false));
-        assertVerifyCredentials(userId, newCredential, newType, sid);
+        initializeStorageWithCredential(userId, oldCredential, sid);
+        assertTrue(mService.setLockCredential(newCredential, oldCredential, userId, false));
+        assertVerifyCredentials(userId, newCredential, sid);
     }
 
-    private void assertVerifyCredentials(int userId, String credential, int type, long sid)
+    private void assertVerifyCredentials(int userId, LockscreenCredential credential, long sid)
             throws RemoteException{
         final long challenge = 54321;
-        VerifyCredentialResponse response = mService.verifyCredential(credential.getBytes(),
-                type, challenge, userId);
+        VerifyCredentialResponse response = mService.verifyCredential(credential,
+                challenge, userId);
 
         assertEquals(GateKeeperResponse.RESPONSE_OK, response.getResponseCode());
         if (sid != -1) assertEquals(sid, mGateKeeperService.getSecureUserId(userId));
-        final int incorrectType;
-        if (type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
-            assertTrue(mService.havePassword(userId));
-            assertFalse(mService.havePattern(userId));
-            incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
-        } else if (type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN){
-            assertFalse(mService.havePassword(userId));
-            assertTrue(mService.havePattern(userId));
-            incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+        if (credential.isPassword()) {
+            assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
+        } else if (credential.isPin()) {
+            assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(userId));
+        } else if (credential.isPattern()) {
+            assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(userId));
         } else {
-            assertFalse(mService.havePassword(userId));
-            assertFalse(mService.havePassword(userId));
-            incorrectType = LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+            assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(userId));
         }
-        // check for bad type
-        assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
-                credential.getBytes(), incorrectType, challenge, userId).getResponseCode());
         // check for bad credential
+        final LockscreenCredential badCredential;
+        if (!credential.isNone()) {
+            badCredential = credential.duplicate();
+            badCredential.getCredential()[0] ^= 1;
+        } else {
+            badCredential = LockscreenCredential.createPin("0");
+        }
         assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
-                ("0" + credential).getBytes(), type, challenge, userId).getResponseCode());
+                badCredential, challenge, userId).getResponseCode());
     }
 
-    private void initializeStorageWithCredential(int userId, String credential, int type, long sid)
-            throws RemoteException {
-        byte[] credentialBytes = credential == null ? null : credential.getBytes();
-        byte[] oldHash = new VerifyHandle(credential.getBytes(), sid).toBytes();
+    private void initializeStorageWithCredential(int userId, LockscreenCredential credential,
+            long sid) throws RemoteException {
+        byte[] oldHash = new VerifyHandle(credential.getCredential(), sid).toBytes();
         if (mService.shouldMigrateToSyntheticPasswordLocked(userId)) {
-            mService.initializeSyntheticPasswordLocked(oldHash, credentialBytes, type,
-                    type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? PASSWORD_QUALITY_ALPHABETIC
-                            : PASSWORD_QUALITY_SOMETHING, userId);
+            mService.initializeSyntheticPasswordLocked(oldHash, credential, userId);
         } else {
-            if (type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD) {
+            if (credential.isPassword() || credential.isPin()) {
                 mStorage.writeCredentialHash(CredentialHash.create(oldHash,
                         LockPatternUtils.CREDENTIAL_TYPE_PASSWORD), userId);
             } else {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
index b60111e..8c2d172 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsShellCommandTest.java
@@ -17,11 +17,13 @@
 package com.android.server.locksettings;
 
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
 import static junit.framework.Assert.assertEquals;
 
-import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.never;
@@ -34,6 +36,8 @@
 import static java.io.FileDescriptor.out;
 
 import android.app.ActivityManager;
+import android.app.admin.PasswordMetrics;
+import android.app.admin.PasswordPolicy;
 import android.content.Context;
 import android.os.Binder;
 import android.os.Handler;
@@ -88,6 +92,7 @@
 
     @Test
     public void testWrongPassword() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
         when(mLockPatternUtils.checkCredential(
@@ -95,18 +100,20 @@
         assertEquals(-1, mCommand.exec(mBinder, in, out, err,
                 new String[] { "set-pin", "--old", "1234" },
                 mShellCallback, mResultReceiver));
-        verify(mLockPatternUtils, never()).setLockCredential(any(), any(),
-                anyInt(), anyBoolean());
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
     }
 
     @Test
     public void testChangePin() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
         when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
                 PASSWORD_QUALITY_NUMERIC);
         when(mLockPatternUtils.checkCredential(
                 LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_NUMERIC));
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-pin", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
@@ -117,6 +124,23 @@
     }
 
     @Test
+    public void testChangePin_nonCompliant() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_NUMERIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPin("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_ALPHABETIC));
+        assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pin", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
+    @Test
     public void testChangePin_noLockScreen() throws Exception {
         when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(false);
         assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
@@ -128,22 +152,42 @@
 
     @Test
     public void testChangePassword() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
         when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
                 PASSWORD_QUALITY_ALPHABETIC);
         when(mLockPatternUtils.checkCredential(
                 LockscreenCredential.createPassword("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_ALPHABETIC));
         assertEquals(0,  mCommand.exec(new Binder(), in, out, err,
-                new String[] { "set-password", "--old", "1234", "4321" },
+                new String[] { "set-password", "--old", "1234", "abcd" },
                 mShellCallback, mResultReceiver));
         verify(mLockPatternUtils).setLockCredential(
-                LockscreenCredential.createPassword("4321"),
+                LockscreenCredential.createPassword("abcd"),
                 LockscreenCredential.createPassword("1234"),
                 mUserId);
     }
 
     @Test
+    public void testChangePassword_nonCompliant() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId)).thenReturn(
+                PASSWORD_QUALITY_ALPHABETIC);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPassword("1234"), mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_COMPLEX));
+        assertEquals(-1,  mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-password", "--old", "1234", "weakpassword" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
+    @Test
     public void testChangePassword_noLockScreen() throws Exception {
         when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(false);
         assertEquals(-1,  mCommand.exec(new Binder(), in, out, err,
@@ -155,11 +199,14 @@
 
     @Test
     public void testChangePattern() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.checkCredential(
                 LockscreenCredential.createPattern(stringToPattern("1234")),
                 mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_SOMETHING));
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "set-pattern", "--old", "1234", "4321" },
                 mShellCallback, mResultReceiver));
@@ -170,6 +217,22 @@
     }
 
     @Test
+    public void testChangePattern_nonCompliant() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_NUMERIC));
+        assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pattern", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
+    @Test
     public void testChangePattern_noLockScreen() throws Exception {
         when(mLockPatternUtils.hasSecureLockScreen()).thenReturn(false);
         assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
@@ -181,11 +244,14 @@
 
     @Test
     public void testClear() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
         when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
         when(mLockPatternUtils.checkCredential(
                 LockscreenCredential.createPattern(stringToPattern("1234")),
                 mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_UNSPECIFIED));
         assertEquals(0, mCommand.exec(new Binder(), in, out, err,
                 new String[] { "clear", "--old", "1234" },
                 mShellCallback, mResultReceiver));
@@ -195,7 +261,29 @@
                 mUserId);
     }
 
+    @Test
+    public void testClear_nonCompliant() throws Exception {
+        when(mLockPatternUtils.isSecure(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkCredential(
+                LockscreenCredential.createPattern(stringToPattern("1234")),
+                mUserId, null)).thenReturn(true);
+        when(mLockPatternUtils.getRequestedPasswordMetrics(mUserId))
+                .thenReturn(metricsForAdminQuality(PASSWORD_QUALITY_SOMETHING));
+        assertEquals(-1, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "clear", "--old", "1234" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils, never()).setLockCredential(any(), any(), anyInt());
+    }
+
     private List<LockPatternView.Cell> stringToPattern(String str) {
         return LockPatternUtils.byteArrayToPattern(str.getBytes());
     }
+
+    private PasswordMetrics metricsForAdminQuality(int quality) {
+        PasswordPolicy policy = new PasswordPolicy();
+        policy.quality = quality;
+        return policy.getMinMetrics();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java
index bc61c58..1581d9a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTestable.java
@@ -16,20 +16,51 @@
 
 package com.android.server.locksettings;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
 import android.content.Context;
 
 import com.android.server.PersistentDataBlockManagerInternal;
 
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
 import java.io.File;
+import java.util.Arrays;
 
 public class LockSettingsStorageTestable extends LockSettingsStorage {
 
     public File mStorageDir;
-    public PersistentDataBlockManagerInternal mPersistentDataBlock;
+    public PersistentDataBlockManagerInternal mPersistentDataBlockManager;
+    private byte[] mPersistentData;
 
     public LockSettingsStorageTestable(Context context, File storageDir) {
         super(context);
         mStorageDir = storageDir;
+        mPersistentDataBlockManager = mock(PersistentDataBlockManagerInternal.class);
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                byte[] handle = (byte[]) invocation.getArguments()[0];
+                if (handle != null) {
+                    mPersistentData = Arrays.copyOf(handle, handle.length);
+                } else {
+                    mPersistentData = null;
+                }
+                return null;
+            }
+        }).when(mPersistentDataBlockManager).setFrpCredentialHandle(any());
+        // For some reasons, simply mocking getFrpCredentialHandle() with
+        // when(mPersistentDataBlockManager.getFrpCredentialHandle()).thenReturn(mPersistentData)
+        // does not work, I had to use the long-winded way below.
+        doAnswer(new Answer<byte[]>() {
+            @Override
+            public byte[] answer(InvocationOnMock invocation) throws Throwable {
+                return mPersistentData;
+            }
+        }).when(mPersistentDataBlockManager).getFrpCredentialHandle();
     }
 
     @Override
@@ -57,8 +88,8 @@
     }
 
     @Override
-    public PersistentDataBlockManagerInternal getPersistentDataBlock() {
-        return mPersistentDataBlock;
+    PersistentDataBlockManagerInternal getPersistentDataBlockManager() {
+        return mPersistentDataBlockManager;
     }
 
     private File makeDirs(File baseDir, String filePath) {
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 cb51897..7a18431 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -240,12 +240,12 @@
         writePasswordBytes(PASSWORD_0, 10);
         writePatternBytes(PATTERN_0, 20);
 
-        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN,
                 mStorage.readCredentialHash(10).type);
         assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
                 mStorage.readCredentialHash(20).type);
         mStorage.clearCache();
-        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN,
                 mStorage.readCredentialHash(10).type);
         assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
                 mStorage.readCredentialHash(20).type);
@@ -352,20 +352,20 @@
     }
 
     public void testPersistentDataBlock_unavailable() {
-        mStorage.mPersistentDataBlock = null;
+        mStorage.mPersistentDataBlockManager = null;
 
         assertSame(PersistentData.NONE, mStorage.readPersistentDataBlock());
     }
 
     public void testPersistentDataBlock_empty() {
-        mStorage.mPersistentDataBlock = mock(PersistentDataBlockManagerInternal.class);
+        mStorage.mPersistentDataBlockManager = mock(PersistentDataBlockManagerInternal.class);
 
         assertSame(PersistentData.NONE, mStorage.readPersistentDataBlock());
     }
 
     public void testPersistentDataBlock_withData() {
-        mStorage.mPersistentDataBlock = mock(PersistentDataBlockManagerInternal.class);
-        when(mStorage.mPersistentDataBlock.getFrpCredentialHandle())
+        mStorage.mPersistentDataBlockManager = mock(PersistentDataBlockManagerInternal.class);
+        when(mStorage.mPersistentDataBlockManager.getFrpCredentialHandle())
                 .thenReturn(PersistentData.toBytes(PersistentData.TYPE_SP_WEAVER, SOME_USER_ID,
                         DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, PAYLOAD));
 
@@ -378,8 +378,8 @@
     }
 
     public void testPersistentDataBlock_exception() {
-        mStorage.mPersistentDataBlock = mock(PersistentDataBlockManagerInternal.class);
-        when(mStorage.mPersistentDataBlock.getFrpCredentialHandle())
+        mStorage.mPersistentDataBlockManager = mock(PersistentDataBlockManagerInternal.class);
+        when(mStorage.mPersistentDataBlockManager.getFrpCredentialHandle())
                 .thenThrow(new IllegalStateException("oops"));
         assertSame(PersistentData.NONE, mStorage.readPersistentDataBlock());
     }
@@ -453,7 +453,7 @@
 
     private void assertPasswordBytes(byte[] password, int userId) {
         CredentialHash cred = mStorage.readCredentialHash(userId);
-        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, cred.type);
+        assertEquals(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN, cred.type);
         assertArrayEquals(password, cred.hash);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
new file mode 100644
index 0000000..df719b6d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.locksettings;
+
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
+import static com.android.internal.widget.LockPatternUtils.USER_FRP;
+
+import android.app.admin.DevicePolicyManager;
+
+import com.android.internal.widget.VerifyCredentialResponse;
+import com.android.server.locksettings.LockSettingsStorage.PersistentData;
+
+
+/** Test setting a lockscreen credential and then verify it under USER_FRP */
+public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        // FRP credential can only be verified prior to provisioning
+        mSettings.setDeviceProvisioned(false);
+    }
+
+    public void testFrpCredential_setPin() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+
+        assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+    }
+
+    public void testFrpCredential_setPattern() {
+        mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID, false);
+
+        assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPattern("4321"), 0, USER_FRP).getResponseCode());
+    }
+
+    public void testFrpCredential_setPassword() {
+        mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID, false);
+
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPassword("4321"), 0, USER_FRP).getResponseCode());
+    }
+
+    public void testFrpCredential_changeCredential() {
+        mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
+        mService.setLockCredential(newPattern("5678"), newPassword("1234"), PRIMARY_USER_ID, false);
+
+        assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPattern("5678"), 0, USER_FRP).getResponseCode());
+    }
+
+    public void testFrpCredential_removeCredential() {
+        mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
+
+        mService.setLockCredential(nonePassword(), newPassword("1234"), PRIMARY_USER_ID, false);
+        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(USER_FRP));
+    }
+
+    public void testFrpCredential_cannotVerifyAfterProvsioning() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+
+        mSettings.setDeviceProvisioned(true);
+        assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
+                mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+    }
+
+    public void testFrpCredential_legacyPinTypePersistentData() {
+        mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+        PersistentData data = mStorage.readPersistentDataBlock();
+        // Tweak the existing persistent data to make it look like one with legacy credential type
+        assertEquals(CREDENTIAL_TYPE_PIN, data.payload[3]);
+        data.payload[3] = CREDENTIAL_TYPE_PASSWORD_OR_PIN;
+        mStorage.writePersistentDataBlock(data.type, data.userId,
+                DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, data.payload);
+
+        assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+
+    }
+
+    public void testFrpCredential_legacyPasswordTypePersistentData() {
+        mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
+        PersistentData data = mStorage.readPersistentDataBlock();
+        // Tweak the existing persistent data to make it look like one with legacy credential type
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, data.payload[3]);
+        data.payload[3] = CREDENTIAL_TYPE_PASSWORD_OR_PIN;
+        mStorage.writePersistentDataBlock(data.type, data.userId,
+                DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, data.payload);
+
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK,
+                mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 42ca42a..89a279c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -16,11 +16,9 @@
 
 package com.android.server.locksettings;
 
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD_OR_PIN;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
 
@@ -38,7 +36,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
@@ -72,15 +69,14 @@
 
     public void testPasswordBasedSyntheticPassword() throws RemoteException {
         final int USER_ID = 10;
-        final byte[] password = "user-password".getBytes();
-        final byte[] badPassword = "bad-password".getBytes();
+        final LockscreenCredential password = newPassword("user-password");
+        final LockscreenCredential badPassword = newPassword("bad-password");
         MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
                 mGateKeeperService, mUserManager, mPasswordSlotManager);
         AuthenticationToken authToken = manager.newSyntheticPasswordAndSid(mGateKeeperService, null,
                 null, USER_ID);
         long handle = manager.createPasswordBasedSyntheticPassword(mGateKeeperService,
-                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, authToken,
-                PASSWORD_QUALITY_ALPHABETIC, USER_ID);
+                password, authToken, USER_ID);
 
         AuthenticationResult result = manager.unwrapPasswordBasedSyntheticPassword(
                 mGateKeeperService, handle, password, USER_ID, null);
@@ -105,97 +101,90 @@
     }
 
     public void testPasswordMigration() throws RemoteException {
-        final byte[] password = "testPasswordMigration-password".getBytes();
+        final LockscreenCredential password = newPassword("testPasswordMigration-password");
 
         disableSyntheticPassword();
-        mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
+        assertTrue(mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false));
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
         enableSyntheticPassword();
         // Performs migration
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                password, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
 
         // SP-based verification
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                password, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertArrayNotEquals(primaryStorageKey,
                 mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
-    protected void initializeCredentialUnderSP(byte[] password, int userId) throws RemoteException {
+    protected void initializeCredentialUnderSP(LockscreenCredential password, int userId)
+            throws RemoteException {
         enableSyntheticPassword();
-        int quality = password != null ? PASSWORD_QUALITY_ALPHABETIC
-                : PASSWORD_QUALITY_UNSPECIFIED;
-        int type = password != null ? LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
-                : LockPatternUtils.CREDENTIAL_TYPE_NONE;
-        mService.setLockCredential(password, type, null, quality, userId, false);
+        mService.setLockCredential(password, nonePassword(), userId, false);
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
+        assertTrue(mService.isSyntheticPasswordBasedCredential(userId));
     }
 
     public void testSyntheticPasswordChangeCredential() throws RemoteException {
-        final byte[] password = "testSyntheticPasswordChangeCredential-password".getBytes();
-        final byte[] newPassword = "testSyntheticPasswordChangeCredential-newpassword".getBytes();
+        final LockscreenCredential password = newPassword("password");
+        final LockscreenCredential newPassword = newPassword("newpassword");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
-        mService.setLockCredential(newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
+        mService.setLockCredential(newPassword, password, PRIMARY_USER_ID, false);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                newPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
     public void testSyntheticPasswordVerifyCredential() throws RemoteException {
-        final byte[] password = "testSyntheticPasswordVerifyCredential-password".getBytes();
-        final byte[] badPassword = "testSyntheticPasswordVerifyCredential-badpassword".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential badPassword = newPassword("badpassword");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                password, 0, PRIMARY_USER_ID)
                         .getResponseCode());
 
         assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
-                badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                badPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
     }
 
     public void testSyntheticPasswordClearCredential() throws RemoteException {
-        final byte[] password = "testSyntheticPasswordClearCredential-password".getBytes();
-        final byte[] badPassword = "testSyntheticPasswordClearCredential-newpassword".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential badPassword = newPassword("newpassword");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         // clear password
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
-                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
+        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
         assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
 
         // set a new password
-        mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
+        mService.setLockCredential(badPassword, nonePassword(),
+                PRIMARY_USER_ID, false);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                badPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
     }
 
     public void testSyntheticPasswordChangeCredentialKeepsAuthSecret() throws RemoteException {
-        final byte[] password =
-                "testSyntheticPasswordChangeCredentialKeepsAuthSecret-password".getBytes();
-        final byte[] badPassword =
-                "testSyntheticPasswordChangeCredentialKeepsAuthSecret-new".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential badPassword = newPassword("new");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
-        mService.setLockCredential(badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
+        mService.setLockCredential(badPassword, password, PRIMARY_USER_ID, false);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                badPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                badPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
 
         // Check the same secret was passed each time
@@ -205,41 +194,35 @@
     }
 
     public void testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret() throws RemoteException {
-        final byte[] password =
-                "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-password".getBytes();
-        final byte[] newPassword =
-                "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-new".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential newPassword = newPassword("new");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         reset(mAuthSecretService);
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+                password, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
     }
 
     public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException {
-        final byte[] password = "testSecondaryUserDoesNotPassAuthSecret-password".getBytes();
+        LockscreenCredential password = newPassword("password");
 
         initializeCredentialUnderSP(password, SECONDARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, SECONDARY_USER_ID)
+                password, 0, SECONDARY_USER_ID)
                         .getResponseCode());
         verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
     }
 
     public void testNoSyntheticPasswordOrCredentialDoesNotPassAuthSecret() throws RemoteException {
-        // Setting null doesn't create a synthetic password
-        initializeCredentialUnderSP(null, PRIMARY_USER_ID);
-
-        reset(mAuthSecretService);
         mService.onUnlockUser(PRIMARY_USER_ID);
         flushHandlerTasks();
         verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
     }
 
     public void testSyntheticPasswordAndCredentialDoesNotPassAuthSecret() throws RemoteException {
-        final byte[] password = "passwordForASyntheticPassword".getBytes();
+        LockscreenCredential password = newPassword("passwordForASyntheticPassword");
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
 
         reset(mAuthSecretService);
@@ -249,10 +232,9 @@
     }
 
     public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
-        final byte[] password = "getASyntheticPassword".getBytes();
+        LockscreenCredential password = newPassword("getASyntheticPassword");
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
-                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
+        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
 
         reset(mAuthSecretService);
         mService.onUnlockUser(PRIMARY_USER_ID);
@@ -261,15 +243,14 @@
     }
 
     public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
-        final byte[] UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd".getBytes();
+        LockscreenCredential UnifiedPassword = newPassword("unified-pwd");
         disableSyntheticPassword();
-        mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
+        mService.setLockCredential(UnifiedPassword, nonePassword(), PRIMARY_USER_ID, false);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
         final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
-        final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
-        final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
+        byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
+        byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
         assertTrue(primarySid != 0);
         assertTrue(profileSid != 0);
         assertTrue(profileSid != primarySid);
@@ -277,12 +258,12 @@
         // do migration
         enableSyntheticPassword();
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                UnifiedPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
 
         // verify
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                UnifiedPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
@@ -295,19 +276,16 @@
     }
 
     public void testManagedProfileSeparateChallengeMigration() throws RemoteException {
-        final byte[] primaryPassword =
-                "testManagedProfileSeparateChallengeMigration-primary".getBytes();
-        final byte[] profilePassword =
-                "testManagedProfileSeparateChallengeMigration-profile".getBytes();
+        LockscreenCredential primaryPassword = newPassword("primary");
+        LockscreenCredential profilePassword = newPassword("profile");
         disableSyntheticPassword();
-        mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
-        mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false);
+        mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID, false);
+        mService.setLockCredential(profilePassword, nonePassword(),
+                MANAGED_PROFILE_USER_ID, false);
         final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
         final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
-        final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
-        final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
+        byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
+        byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
         assertTrue(primarySid != 0);
         assertTrue(profileSid != 0);
         assertTrue(profileSid != primarySid);
@@ -315,19 +293,19 @@
         // do migration
         enableSyntheticPassword();
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                primaryPassword, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                0, MANAGED_PROFILE_USER_ID).getResponseCode());
+                profilePassword, 0, MANAGED_PROFILE_USER_ID)
+                .getResponseCode());
 
         // verify
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                        .getResponseCode());
+                primaryPassword, 0, PRIMARY_USER_ID)
+                .getResponseCode());
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                0, MANAGED_PROFILE_USER_ID).getResponseCode());
+                profilePassword, 0, MANAGED_PROFILE_USER_ID)
+                .getResponseCode());
         assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
         assertArrayNotEquals(primaryStorageKey,
@@ -339,101 +317,92 @@
     }
 
     public void testTokenBasedResetPassword() throws RemoteException {
-        final byte[] password = "password".getBytes();
-        final byte[] pattern = "123654".getBytes();
-        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential pattern = newPattern("123654");
+        byte[] token = "some-high-entropy-secure-token".getBytes();
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         // Disregard any reportPasswordChanged() invocations as part of credential setup.
         flushHandlerTasks();
         reset(mDevicePolicyManager);
 
-        final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
+        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
 
         assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
         long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
 
-        mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
-                PRIMARY_USER_ID).getResponseCode();
+        mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
 
-        mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
-                handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
+        mLocalService.setLockCredentialWithToken(pattern, handle, token, PRIMARY_USER_ID);
 
         // Verify DPM gets notified about new device lock
         flushHandlerTasks();
-        final PasswordMetrics metric = PasswordMetrics.computeForCredential(
-                LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(pattern)));
+        final PasswordMetrics metric = PasswordMetrics.computeForCredential(pattern);
         assertEquals(metric, mService.getUserPasswordMetrics(PRIMARY_USER_ID));
         verify(mDevicePolicyManager).reportPasswordChanged(PRIMARY_USER_ID);
 
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
+                pattern, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
     public void testTokenBasedClearPassword() throws RemoteException {
-        final byte[] password = "password".getBytes();
-        final byte[] pattern = "123654".getBytes();
-        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential pattern = newPattern("123654");
+        byte[] token = "some-high-entropy-secure-token".getBytes();
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
-        final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
+        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
 
         long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                0, PRIMARY_USER_ID).getResponseCode();
+        mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mLocalService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
-                handle, token, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+        mLocalService.setLockCredentialWithToken(nonePassword(), handle, token, PRIMARY_USER_ID);
         flushHandlerTasks(); // flush the unlockUser() call before changing password again
-        mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
-                handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
+        mLocalService.setLockCredentialWithToken(pattern, handle, token,
+                PRIMARY_USER_ID);
 
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID)
+                pattern, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
     public void testTokenBasedResetPasswordAfterCredentialChanges() throws RemoteException {
-        final byte[] password = "password".getBytes();
-        final byte[] pattern = "123654".getBytes();
-        final byte[] newPassword = "password".getBytes();
-        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential pattern = newPattern("123654");
+        LockscreenCredential newPassword = newPassword("password");
+        byte[] token = "some-high-entropy-secure-token".getBytes();
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
-        final byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
+        byte[] storageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
 
         long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.verifyCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                0, PRIMARY_USER_ID).getResponseCode();
+        mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, password,
-                PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false);
+        mService.setLockCredential(pattern, password, PRIMARY_USER_ID, false);
 
-        mLocalService.setLockCredentialWithToken(newPassword,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+        mLocalService.setLockCredentialWithToken(newPassword, handle, token, PRIMARY_USER_ID);
 
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                newPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                newPassword, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
     public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNeedsMigration()
             throws RemoteException {
-        final String token = "some-high-entropy-secure-token";
+        final byte[] token = "some-high-entropy-secure-token".getBytes();
         enableSyntheticPassword();
-        long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
+        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
@@ -441,9 +410,15 @@
 
     public void testEscrowTokenActivatedImmediatelyIfNoUserPasswordNoMigration()
             throws RemoteException {
-        final String token = "some-high-entropy-secure-token";
-        initializeCredentialUnderSP(null, PRIMARY_USER_ID);
-        long handle = mLocalService.addEscrowToken(token.getBytes(), PRIMARY_USER_ID, null);
+        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        // By first setting a password and then clearing it, we enter the state where SP is
+        // initialized but the user currently has no password
+        initializeCredentialUnderSP(newPassword("password"), PRIMARY_USER_ID);
+        assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
+                PRIMARY_USER_ID, false));
+        assertTrue(mService.isSyntheticPasswordBasedCredential(PRIMARY_USER_ID));
+
+        long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
         assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
@@ -451,12 +426,11 @@
 
     public void testEscrowTokenActivatedLaterWithUserPasswordNeedsMigration()
             throws RemoteException {
-        final byte[] token = "some-high-entropy-secure-token".getBytes();
-        final byte[] password = "password".getBytes();
+        byte[] token = "some-high-entropy-secure-token".getBytes();
+        LockscreenCredential password = newPassword("password");
         // Set up pre-SP user password
         disableSyntheticPassword();
-        mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
+        mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false);
         enableSyntheticPassword();
 
         long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
@@ -464,14 +438,14 @@
         assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
         // Activate token (password gets migrated to SP at the same time)
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                password, 0, PRIMARY_USER_ID)
                     .getResponseCode());
         // Verify token is activated
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
     }
 
     public void testEscrowTokenCannotBeActivatedOnUnmanagedUser() {
-        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        byte[] token = "some-high-entropy-secure-token".getBytes();
         when(mUserManagerInternal.isDeviceManaged()).thenReturn(false);
         when(mUserManagerInternal.isUserManaged(PRIMARY_USER_ID)).thenReturn(false);
         when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true);
@@ -483,9 +457,9 @@
     }
 
     public void testSetLockCredentialWithTokenFailsWithoutLockScreen() throws Exception {
-        final byte[] password = "password".getBytes();
-        final byte[] pattern = "123654".getBytes();
-        final byte[] token = "some-high-entropy-secure-token".getBytes();
+        LockscreenCredential password = newPassword("password");
+        LockscreenCredential pattern = newPattern("123654");
+        byte[] token = "some-high-entropy-secure-token".getBytes();
 
         mHasSecureLockScreen = false;
         enableSyntheticPassword();
@@ -493,57 +467,50 @@
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
         try {
-            mLocalService.setLockCredentialWithToken(password,
-                    LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, handle, token,
-                    PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+            mLocalService.setLockCredentialWithToken(password, handle, token, PRIMARY_USER_ID);
             fail("An exception should have been thrown.");
         } catch (UnsupportedOperationException e) {
             // Success - the exception was expected.
         }
-        assertFalse(mService.havePassword(PRIMARY_USER_ID));
+        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
 
         try {
-            mLocalService.setLockCredentialWithToken(pattern,
-                    LockPatternUtils.CREDENTIAL_TYPE_PATTERN, handle, token,
-                    PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+            mLocalService.setLockCredentialWithToken(pattern, handle, token, PRIMARY_USER_ID);
             fail("An exception should have been thrown.");
         } catch (UnsupportedOperationException e) {
             // Success - the exception was expected.
         }
-        assertFalse(mService.havePattern(PRIMARY_USER_ID));
+        assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
     }
 
     public void testGetHashFactorPrimaryUser() throws RemoteException {
-        final byte[] password = "password".getBytes();
-        mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
-        final byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
+        LockscreenCredential password = newPassword("password");
+        mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false);
+        byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
         assertNotNull(hashFactor);
 
-        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
-                password, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID, false);
-        final byte[] newHashFactor = mService.getHashFactor(null, PRIMARY_USER_ID);
+        mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
+        byte[] newHashFactor = mService.getHashFactor(nonePassword(), PRIMARY_USER_ID);
         assertNotNull(newHashFactor);
         // Hash factor should never change after password change/removal
         assertArrayEquals(hashFactor, newHashFactor);
     }
 
     public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
-        final byte[] pattern = "1236".getBytes();
-        mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
-                null, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID, false);
+        LockscreenCredential pattern = newPattern("1236");
+        mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID, false);
         mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
         assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
     }
 
     public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
-        final byte[] primaryPassword = "primary".getBytes();
-        final byte[] profilePassword = "profile".getBytes();
-        mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
-        mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false);
-        assertNotNull(mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
+        LockscreenCredential primaryPassword = newPassword("primary");
+        LockscreenCredential profilePassword = newPassword("profile");
+        mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID, false);
+        mService.setLockCredential(profilePassword, nonePassword(),
+                MANAGED_PROFILE_USER_ID, false);
+        assertNotNull(
+                mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
     }
 
     public void testPasswordData_serializeDeserialize() {
@@ -551,7 +518,7 @@
         data.scryptN = 11;
         data.scryptR = 22;
         data.scryptP = 33;
-        data.passwordType = CREDENTIAL_TYPE_PASSWORD;
+        data.credentialType = CREDENTIAL_TYPE_PASSWORD;
         data.salt = PAYLOAD;
         data.passwordHandle = PAYLOAD2;
 
@@ -560,7 +527,7 @@
         assertEquals(11, deserialized.scryptN);
         assertEquals(22, deserialized.scryptR);
         assertEquals(33, deserialized.scryptP);
-        assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType);
+        assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.credentialType);
         assertArrayEquals(PAYLOAD, deserialized.salt);
         assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
     }
@@ -569,7 +536,7 @@
         // Test that we can deserialize existing PasswordData and don't inadvertently change the
         // wire format.
         byte[] serialized = new byte[] {
-                0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD */
+                0, 0, 0, 2, /* CREDENTIAL_TYPE_PASSWORD_OR_PIN */
                 11, /* scryptN */
                 22, /* scryptR */
                 33, /* scryptP */
@@ -583,7 +550,7 @@
         assertEquals(11, deserialized.scryptN);
         assertEquals(22, deserialized.scryptR);
         assertEquals(33, deserialized.scryptP);
-        assertEquals(CREDENTIAL_TYPE_PASSWORD, deserialized.passwordType);
+        assertEquals(CREDENTIAL_TYPE_PASSWORD_OR_PIN, deserialized.credentialType);
         assertArrayEquals(PAYLOAD, deserialized.salt);
         assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
     }
@@ -591,11 +558,11 @@
     public void testGsiDisablesAuthSecret() throws RemoteException {
         mGsiService.setIsGsiRunning(true);
 
-        final byte[] password = "testGsiDisablesAuthSecret-password".getBytes();
+        LockscreenCredential password = newPassword("testGsiDisablesAuthSecret-password");
 
         initializeCredentialUnderSP(password, PRIMARY_USER_ID);
         assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+                password, 0, PRIMARY_USER_ID)
                         .getResponseCode());
         verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index a992dd1..7d3ec03 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -23,6 +23,7 @@
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
+import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -31,7 +32,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -162,21 +162,6 @@
     }
 
     @Test
-    public void isPin_isTrueForNumericString() {
-        assertTrue(KeySyncTask.isPin("3298432574398654376547".getBytes()));
-    }
-
-    @Test
-    public void isPin_isFalseForStringContainingLetters() {
-        assertFalse(KeySyncTask.isPin("398i54369548654".getBytes()));
-    }
-
-    @Test
-    public void isPin_isFalseForStringContainingSymbols() {
-        assertFalse(KeySyncTask.isPin("-3987543643".getBytes()));
-    }
-
-    @Test
     public void hashCredentialsBySaltedSha256_returnsSameHashForSameCredentialsAndSalt() {
         String credentials = "password1234";
         byte[] salt = randomBytes(16);
@@ -221,19 +206,19 @@
     @Test
     public void getUiFormat_returnsPinIfPin() {
         assertEquals(UI_FORMAT_PIN,
-                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234".getBytes()));
+                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PIN));
     }
 
     @Test
     public void getUiFormat_returnsPasswordIfPassword() {
         assertEquals(UI_FORMAT_PASSWORD,
-                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD, "1234a".getBytes()));
+                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PASSWORD));
     }
 
     @Test
     public void getUiFormat_returnsPatternIfPattern() {
         assertEquals(UI_FORMAT_PATTERN,
-                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PATTERN, "1234".getBytes()));
+                KeySyncTask.getUiFormat(CREDENTIAL_TYPE_PATTERN));
 
     }
 
@@ -683,7 +668,7 @@
                 mRecoverySnapshotStorage,
                 mSnapshotListenersStorage,
                 TEST_USER_ID,
-                CREDENTIAL_TYPE_PASSWORD,
+                CREDENTIAL_TYPE_PIN,
                 /*credential=*/ pin.getBytes(),
                 /*credentialUpdated=*/ false,
                 mPlatformKeyManager,
@@ -799,7 +784,7 @@
           mRecoverySnapshotStorage,
           mSnapshotListenersStorage,
           TEST_USER_ID,
-          /*credentialType=*/ 3,
+          /*credentialType=*/ 5, // Some invalid credential type value
           "12345".getBytes(),
           /*credentialUpdated=*/ false,
           mPlatformKeyManager,
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index fe7a376..25b41db 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -29,7 +29,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
 import android.util.Log;
@@ -88,17 +87,11 @@
 
     private static final int REPEAT_TEST_COUNT = 5;
 
-    private static final String KEY_PAROLE_DURATION = "parole_duration";
-    private static final String DESIRED_PAROLE_DURATION = "0";
-
     private static Context mContext;
     private static UiDevice mUiDevice;
     private static int mTestPkgUid;
     private static BatteryManager mBatteryManager;
 
-    private static boolean mAppIdleConstsUpdated;
-    private static String mOriginalAppIdleConsts;
-
     private static ServiceConnection mServiceConnection;
     private static ICmdReceiverService mCmdReceiverService;
 
@@ -107,7 +100,6 @@
         mContext = InstrumentationRegistry.getContext();
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
 
-        setDesiredParoleDuration();
         mContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG,
                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
         mTestPkgUid = mContext.getPackageManager().getPackageUid(TEST_PKG, 0);
@@ -119,10 +111,6 @@
     @AfterClass
     public static void tearDownOnce() throws Exception {
         batteryReset();
-        if (mAppIdleConstsUpdated) {
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.APP_IDLE_CONSTANTS, mOriginalAppIdleConsts);
-        }
         unbindService();
     }
 
@@ -160,27 +148,6 @@
         }
     }
 
-    private static void setDesiredParoleDuration() {
-        mOriginalAppIdleConsts = Settings.Global.getString(mContext.getContentResolver(),
-                Settings.Global.APP_IDLE_CONSTANTS);
-        String newAppIdleConstants;
-        final String newConstant = KEY_PAROLE_DURATION + "=" + DESIRED_PAROLE_DURATION;
-        if (mOriginalAppIdleConsts == null || "null".equals(mOriginalAppIdleConsts)) {
-            // app_idle_constants is initially empty, so just assign the desired value.
-            newAppIdleConstants = newConstant;
-        } else if (mOriginalAppIdleConsts.contains(KEY_PAROLE_DURATION)) {
-            // app_idle_constants contains parole_duration, so replace it with the desired value.
-            newAppIdleConstants = mOriginalAppIdleConsts.replaceAll(
-                    KEY_PAROLE_DURATION + "=\\d+", newConstant);
-        } else {
-            // app_idle_constants didn't have parole_duration, so append the desired value.
-            newAppIdleConstants = mOriginalAppIdleConsts + "," + newConstant;
-        }
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.APP_IDLE_CONSTANTS, newAppIdleConstants);
-        mAppIdleConstsUpdated = true;
-    }
-
     @Test
     public void testStartActivity_batterySaver() throws Exception {
         setBatterySaverMode(true);
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java
new file mode 100644
index 0000000..23f1281
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/HarmfulCrcsTests.java
@@ -0,0 +1,60 @@
+/*
+ * 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.server.net.watchlist;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.HexDump;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/**
+ * runtest frameworks-services -c com.android.server.net.watchlist.HarmfulCrcTests
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class HarmfulCrcsTests {
+
+    private static final byte[] TEST_DIGEST = HexDump.hexStringToByteArray("AABBCCDD");
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testHarmfulCrcs_setAndContains() throws Exception {
+        HarmfulCrcs harmfulCrcs = new HarmfulCrcs(
+                Arrays.asList(new byte[][] {TEST_DIGEST}));
+        assertTrue(harmfulCrcs.contains(0xaabbccdd));
+        assertFalse(harmfulCrcs.contains(0xbbbbbbbb));
+        assertFalse(harmfulCrcs.contains(0x01020304));
+        assertFalse(harmfulCrcs.contains(0xddccbbaa));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
new file mode 100644
index 0000000..6bb4202
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -0,0 +1,298 @@
+/*
+ * 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.pm;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.apex.ApexInfo;
+import android.apex.ApexSessionInfo;
+import android.apex.IApexService;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.os.FileUtils;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.servicestests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ApexManagerTest {
+    private static final String TEST_APEX_PKG = "com.android.apex.test";
+    private static final int TEST_SESSION_ID = 99999999;
+    private static final int[] TEST_CHILD_SESSION_ID = {8888, 7777};
+    private ApexManager mApexManager;
+    private Context mContext;
+
+    private IApexService mApexService = mock(IApexService.class);
+
+    @Before
+    public void setUp() throws RemoteException {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mApexManager = new ApexManager.ApexManagerImpl(mContext, mApexService);
+    }
+
+    @Test
+    public void testGetPackageInfo_setFlagsMatchActivePackage() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+        final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
+                ApexManager.MATCH_ACTIVE_PACKAGE);
+
+        assertThat(activePkgPi).isNotNull();
+        assertThat(activePkgPi.packageName).contains(TEST_APEX_PKG);
+
+        final PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
+                ApexManager.MATCH_FACTORY_PACKAGE);
+
+        assertThat(factoryPkgPi).isNull();
+    }
+
+    @Test
+    public void testGetPackageInfo_setFlagsMatchFactoryPackage() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+        PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
+                ApexManager.MATCH_FACTORY_PACKAGE);
+
+        assertThat(factoryPkgPi).isNotNull();
+        assertThat(factoryPkgPi.packageName).contains(TEST_APEX_PKG);
+
+        final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
+                ApexManager.MATCH_ACTIVE_PACKAGE);
+
+        assertThat(activePkgPi).isNull();
+    }
+
+    @Test
+    public void testGetPackageInfo_setFlagsNone() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+
+        assertThat(mApexManager.getPackageInfo(TEST_APEX_PKG, 0)).isNull();
+    }
+
+    @Test
+    public void testGetActivePackages() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
+
+        assertThat(mApexManager.getActivePackages()).isNotEmpty();
+    }
+
+    @Test
+    public void testGetActivePackages_noneActivePackages() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+
+        assertThat(mApexManager.getActivePackages()).isEmpty();
+    }
+
+    @Test
+    public void testGetFactoryPackages() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+
+        assertThat(mApexManager.getFactoryPackages()).isNotEmpty();
+    }
+
+    @Test
+    public void testGetFactoryPackages_noneFactoryPackages() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+
+        assertThat(mApexManager.getFactoryPackages()).isEmpty();
+    }
+
+    @Test
+    public void testGetInactivePackages() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+
+        assertThat(mApexManager.getInactivePackages()).isNotEmpty();
+    }
+
+    @Test
+    public void testGetInactivePackages_noneInactivePackages() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+
+        assertThat(mApexManager.getInactivePackages()).isEmpty();
+    }
+
+    @Test
+    public void testIsApexPackage() throws RemoteException {
+        when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+
+        assertThat(mApexManager.isApexPackage(TEST_APEX_PKG)).isTrue();
+    }
+
+    @Test
+    public void testIsApexSupported() {
+        assertThat(mApexManager.isApexSupported()).isTrue();
+    }
+
+    @Test
+    public void testGetStagedSessionInfo() throws RemoteException {
+        when(mApexService.getStagedSessionInfo(anyInt())).thenReturn(
+                getFakeStagedSessionInfo());
+
+        mApexManager.getStagedSessionInfo(TEST_SESSION_ID);
+        verify(mApexService, times(1)).getStagedSessionInfo(TEST_SESSION_ID);
+    }
+
+    @Test
+    public void testGetStagedSessionInfo_unKnownStagedSessionId() throws RemoteException {
+        when(mApexService.getStagedSessionInfo(anyInt())).thenReturn(
+                getFakeUnknownSessionInfo());
+
+        assertThat(mApexManager.getStagedSessionInfo(TEST_SESSION_ID)).isNull();
+    }
+
+    @Test
+    public void testSubmitStagedSession_throwPackageManagerException() throws RemoteException {
+        doAnswer(invocation -> {
+            throw new Exception();
+        }).when(mApexService).submitStagedSession(anyInt(), any(), any());
+
+        assertThrows(PackageManagerException.class,
+                () -> mApexManager.submitStagedSession(TEST_SESSION_ID, TEST_CHILD_SESSION_ID));
+    }
+
+    @Test
+    public void testSubmitStagedSession_throwRunTimeException() throws RemoteException {
+        doThrow(RemoteException.class).when(mApexService).submitStagedSession(anyInt(), any(),
+                any());
+
+        assertThrows(RuntimeException.class,
+                () -> mApexManager.submitStagedSession(TEST_SESSION_ID, TEST_CHILD_SESSION_ID));
+    }
+
+    @Test
+    public void testMarkStagedSessionReady_throwPackageManagerException() throws RemoteException {
+        doAnswer(invocation -> {
+            throw new Exception();
+        }).when(mApexService).markStagedSessionReady(anyInt());
+
+        assertThrows(PackageManagerException.class,
+                () -> mApexManager.markStagedSessionReady(TEST_SESSION_ID));
+    }
+
+    @Test
+    public void testMarkStagedSessionReady_throwRunTimeException() throws RemoteException {
+        doThrow(RemoteException.class).when(mApexService).markStagedSessionReady(anyInt());
+
+        assertThrows(RuntimeException.class,
+                () -> mApexManager.markStagedSessionReady(TEST_SESSION_ID));
+    }
+
+    @Test
+    public void testAbortActiveSession_remoteException() throws RemoteException {
+        doThrow(RemoteException.class).when(mApexService).abortActiveSession();
+
+        try {
+            assertThat(mApexManager.abortActiveSession()).isFalse();
+        } catch (Exception e) {
+            throw new AssertionError("ApexManager should not raise Exception");
+        }
+    }
+
+    @Test
+    public void testMarkStagedSessionSuccessful_throwRemoteException() throws RemoteException {
+        doThrow(RemoteException.class).when(mApexService).markStagedSessionSuccessful(anyInt());
+
+        assertThrows(RuntimeException.class,
+                () -> mApexManager.markStagedSessionSuccessful(TEST_SESSION_ID));
+    }
+
+    @Test
+    public void testUninstallApex_throwException_returnFalse() throws RemoteException {
+        doAnswer(invocation -> {
+            throw new Exception();
+        }).when(mApexService).unstagePackages(any());
+
+        assertThat(mApexManager.uninstallApex(TEST_APEX_PKG)).isFalse();
+    }
+
+    private ApexInfo[] createApexInfo(boolean isActive, boolean isFactory) {
+        File apexFile = copyRawResourceToFile(TEST_APEX_PKG, R.raw.apex_test);
+        ApexInfo apexInfo = new ApexInfo();
+        apexInfo.isActive = isActive;
+        apexInfo.isFactory = isFactory;
+        apexInfo.moduleName = TEST_APEX_PKG;
+        apexInfo.modulePath = apexFile.getPath();
+        apexInfo.versionCode = 191000070;
+
+        return new ApexInfo[]{apexInfo};
+    }
+
+    private ApexSessionInfo getFakeStagedSessionInfo() {
+        ApexSessionInfo stagedSessionInfo = new ApexSessionInfo();
+        stagedSessionInfo.sessionId = TEST_SESSION_ID;
+        stagedSessionInfo.isStaged = true;
+
+        return stagedSessionInfo;
+    }
+
+    private ApexSessionInfo getFakeUnknownSessionInfo() {
+        ApexSessionInfo stagedSessionInfo = new ApexSessionInfo();
+        stagedSessionInfo.sessionId = TEST_SESSION_ID;
+        stagedSessionInfo.isUnknown = true;
+
+        return stagedSessionInfo;
+    }
+
+    /**
+     * Copies a specified {@code resourceId} to a temp file. Returns a non-null file if the copy
+     * succeeded
+     */
+    File copyRawResourceToFile(String baseName, int resourceId) {
+        File outFile;
+        try {
+            outFile = File.createTempFile(baseName, ".apex");
+        } catch (IOException e) {
+            throw new AssertionError("CreateTempFile IOException" + e);
+        }
+
+        try (InputStream is = mContext.getResources().openRawResource(resourceId);
+             FileOutputStream os = new FileOutputStream(outFile)) {
+            assertThat(FileUtils.copy(is, os)).isGreaterThan(0L);
+        } catch (FileNotFoundException e) {
+            throw new AssertionError("File not found exception " + e);
+        } catch (IOException e) {
+            throw new AssertionError("IOException" + e);
+        }
+
+        return outFile;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 7c2a097..3c10447 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -165,9 +165,8 @@
                 /* stagingManager */ null,
                 /* sessionId */ sessionId,
                 /* userId */  456,
-                /* installerPackageName */ "testInstaller",
                 /* installerUid */ -1,
-                InstallSource.create("testInstaller"),
+                /* installSource */ InstallSource.create("testInstaller", "testInstaller"),
                 /* sessionParams */ params,
                 /* createdMillis */ 0L,
                 /* stageDir */ mTmpDir,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 15032c5..1106be2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -812,11 +812,9 @@
         assertSame(origPkgSetting.cpuAbiOverrideString, testPkgSetting.cpuAbiOverrideString);
         assertThat(origPkgSetting.cpuAbiOverrideString, is(testPkgSetting.cpuAbiOverrideString));
         assertThat(origPkgSetting.firstInstallTime, is(testPkgSetting.firstInstallTime));
-        assertSame(origPkgSetting.installerPackageName, testPkgSetting.installerPackageName);
-        assertThat(origPkgSetting.installerPackageName, is(testPkgSetting.installerPackageName));
+        assertSame(origPkgSetting.installSource, testPkgSetting.installSource);
         assertThat(origPkgSetting.installPermissionsFixed,
                 is(testPkgSetting.installPermissionsFixed));
-        assertThat(origPkgSetting.isOrphaned, is(testPkgSetting.isOrphaned));
         assertSame(origPkgSetting.keySetData, testPkgSetting.keySetData);
         assertThat(origPkgSetting.keySetData, is(testPkgSetting.keySetData));
         assertThat(origPkgSetting.lastUpdateTime, is(testPkgSetting.lastUpdateTime));
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 05905d9..3ea3b3c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -429,7 +429,7 @@
 
         final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
 
-        assertThat(scanResult.pkgSetting.isOrphaned, is(true));
+        assertThat(scanResult.pkgSetting.installSource.isOrphaned, is(true));
     }
 
     private static Matcher<Integer> hasFlag(final int flag) {
diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
index 0c5451f..a83d940 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -106,6 +106,11 @@
         return createPackageRollbackInfo(packageName, new int[] {});
     }
 
+    private static Rollback createRollbackForId(int rollbackId) {
+        return new Rollback(rollbackId, new File("/does/not/exist"), -1,
+                0, "com.xyz");
+    }
+
     @Test
     public void testRestoreAppDataSnapshot_pendingBackupForUser() throws Exception {
         Installer installer = mock(Installer.class);
@@ -232,18 +237,16 @@
         wasRecentlyRestored.getPendingRestores().add(
                 new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));
 
-        Rollback dataWithPendingBackup = new Rollback(101, new File("/does/not/exist"), -1);
+        Rollback dataWithPendingBackup = createRollbackForId(101);
         dataWithPendingBackup.info.getPackages().add(pendingBackup);
 
-        Rollback dataWithRecentRestore = new Rollback(17239, new File("/does/not/exist"),
-                -1);
+        Rollback dataWithRecentRestore = createRollbackForId(17239);
         dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored);
 
-        Rollback dataForDifferentUser = new Rollback(17239, new File("/does/not/exist"),
-                -1);
+        Rollback dataForDifferentUser = createRollbackForId(17239);
         dataForDifferentUser.info.getPackages().add(ignoredInfo);
 
-        Rollback dataForRestore = new Rollback(17239, new File("/does/not/exist"), -1);
+        Rollback dataForRestore = createRollbackForId(17239);
         dataForRestore.info.getPackages().add(pendingRestore);
         dataForRestore.info.getPackages().add(wasRecentlyRestored);
 
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
index ee3b15a..aec489c 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
@@ -43,6 +43,8 @@
 public class RollbackStoreTest {
 
     private static final int ID = 123;
+    private static final int USER = 0;
+    private static final String INSTALLER = "some.installer";
 
     private static final Correspondence<VersionedPackage, VersionedPackage> VER_PKG_CORR =
             new Correspondence<VersionedPackage, VersionedPackage>() {
@@ -97,7 +99,8 @@
             + "'longVersionCode':23},{'packageName':'something','longVersionCode':999}],"
             + "'committedSessionId':45654465},'timestamp':'2019-10-01T12:29:08.855Z',"
             + "'stagedSessionId':-1,'state':'enabling','apkSessionId':-1,"
-            + "'restoreUserDataInProgress':true}";
+            + "'restoreUserDataInProgress':true, 'userId':0,"
+            + "'installerPackageName':'some.installer'}";
 
     @Rule
     public TemporaryFolder mFolder = new TemporaryFolder();
@@ -115,7 +118,7 @@
 
     @Test
     public void createNonStaged() {
-        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         assertThat(rollback.getBackupDir().getAbsolutePath())
                 .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
@@ -128,7 +131,7 @@
 
     @Test
     public void createStaged() {
-        Rollback rollback = mRollbackStore.createStagedRollback(ID, 897);
+        Rollback rollback = mRollbackStore.createStagedRollback(ID, 897, USER, INSTALLER);
 
         assertThat(rollback.getBackupDir().getAbsolutePath())
                 .isEqualTo(mFolder.getRoot().getAbsolutePath() + "/" + ID);
@@ -143,7 +146,7 @@
 
     @Test
     public void saveAndLoadRollback() {
-        Rollback origRb = mRollbackStore.createNonStagedRollback(ID);
+        Rollback origRb = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         origRb.setRestoreUserDataInProgress(true);
         origRb.info.getCausePackages().add(new VersionedPackage("com.made.up", 2));
@@ -193,7 +196,7 @@
 
     @Test
     public void loadFromJson() throws Exception {
-        Rollback expectedRb = mRollbackStore.createNonStagedRollback(ID);
+        Rollback expectedRb = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         expectedRb.setTimestamp(Instant.parse("2019-10-01T12:29:08.855Z"));
         expectedRb.setRestoreUserDataInProgress(true);
@@ -242,7 +245,7 @@
 
     @Test
     public void saveAndDelete() {
-        Rollback rollback = mRollbackStore.createNonStagedRollback(ID);
+        Rollback rollback = mRollbackStore.createNonStagedRollback(ID, USER, INSTALLER);
 
         RollbackStore.saveRollback(rollback);
 
@@ -287,6 +290,9 @@
             assertPackageRollbacksAreEquivalent(
                     b.info.getPackages().get(i), a.info.getPackages().get(i));
         }
+
+        assertThat(a.getUserId()).isEqualTo(b.getUserId());
+        assertThat(a.getInstallerPackageName()).isEqualTo(b.getInstallerPackageName());
     }
 
     private void assertPackageRollbacksAreEquivalent(PackageRollbackInfo b, PackageRollbackInfo a) {
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
index 151b6e2..e368d63 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
@@ -52,6 +52,8 @@
     private static final String PKG_2 = "test.testpackage.pkg2";
     private static final String PKG_3 = "com.blah.hello.three";
     private static final String PKG_4 = "com.something.4pack";
+    private static final int USER = 0;
+    private static final String INSTALLER = "some.installer";
 
     @Mock private AppDataRollbackHelper mMockDataHelper;
 
@@ -66,7 +68,7 @@
         int sessionId = 567;
         File file = new File("/test/testing");
 
-        Rollback rollback = new Rollback(rollbackId, file, sessionId);
+        Rollback rollback = new Rollback(rollbackId, file, sessionId, USER, INSTALLER);
 
         assertThat(rollback.isEnabling()).isTrue();
         assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
@@ -79,7 +81,7 @@
         int rollbackId = 123;
         File file = new File("/test/testing");
 
-        Rollback rollback = new Rollback(rollbackId, file, -1);
+        Rollback rollback = new Rollback(rollbackId, file, -1, USER, INSTALLER);
 
         assertThat(rollback.isEnabling()).isTrue();
         assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
@@ -88,7 +90,8 @@
 
     @Test
     public void rollbackMadeAvailable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER,
+                INSTALLER);
 
         assertThat(rollback.isEnabling()).isTrue();
         assertThat(rollback.isAvailable()).isFalse();
@@ -106,7 +109,7 @@
 
     @Test
     public void deletedRollbackCannotBeMadeAvailable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
 
         rollback.delete(mMockDataHelper);
 
@@ -120,7 +123,7 @@
 
     @Test
     public void getPackageNamesAllAndJustApex() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 11, true);
         PackageRollbackInfo pkgInfo3 = newPkgInfoFor(PKG_3, 19, 1, false);
@@ -134,7 +137,7 @@
 
     @Test
     public void includesPackagesAfterEnable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         PackageRollbackInfo pkgInfo3 = newPkgInfoFor(PKG_3, 157, 156, false);
@@ -162,7 +165,7 @@
 
     @Test
     public void snapshotWhenEnabling() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -180,7 +183,7 @@
 
     @Test
     public void snapshotWhenAvailable() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -201,7 +204,7 @@
 
     @Test
     public void snapshotWhenDeleted() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -222,7 +225,7 @@
 
     @Test
     public void snapshotThenDelete() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -242,7 +245,7 @@
 
     @Test
     public void restoreUserDataDoesNothingIfNotInProgress() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -257,7 +260,7 @@
 
     @Test
     public void restoreUserDataDoesNothingIfPackageNotFound() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
@@ -273,7 +276,7 @@
 
     @Test
     public void restoreUserDataRestoresIfInProgressAndPackageFound() {
-        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER);
         PackageRollbackInfo pkgInfo1 = newPkgInfoFor(PKG_1, 12, 10, false);
         PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true);
         rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2));
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java b/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java
index 9e00077..d797955 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/SimpleTimeZoneDetectorStrategyTest.java
@@ -23,7 +23,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.app.timedetector.TimeSignal;
+import android.app.timedetector.PhoneTimeSuggestion;
 import android.content.Intent;
 import android.icu.util.Calendar;
 import android.icu.util.GregorianCalendar;
@@ -45,6 +45,8 @@
             .setActualTimeUtc(2018, 1, 1, 12, 0, 0)
             .build();
 
+    private static final int ARBITRARY_PHONE_ID = 123456;
+
     private Script mScript;
 
     @Before
@@ -53,30 +55,32 @@
     }
 
     @Test
-    public void testSuggestTime_nitz_timeDetectionEnabled() {
+    public void testSuggestPhoneTime_nitz_timeDetectionEnabled() {
         Scenario scenario = SCENARIO_1;
         mScript.pokeFakeClocks(scenario)
                 .pokeTimeDetectionEnabled(true);
 
-        TimeSignal timeSignal = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
+        PhoneTimeSuggestion timeSuggestion =
+                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
         final int clockIncrement = 1000;
         long expectSystemClockMillis = scenario.getActualTimeMillis() + clockIncrement;
 
         mScript.simulateTimePassing(clockIncrement)
-                .simulateTimeSignalReceived(timeSignal)
+                .simulatePhoneTimeSuggestion(timeSuggestion)
                 .verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis);
     }
 
     @Test
-    public void testSuggestTime_systemClockThreshold() {
+    public void testSuggestPhoneTime_systemClockThreshold() {
         Scenario scenario = SCENARIO_1;
         final int systemClockUpdateThresholdMillis = 1000;
         mScript.pokeFakeClocks(scenario)
                 .pokeThresholds(systemClockUpdateThresholdMillis)
                 .pokeTimeDetectionEnabled(true);
 
-        TimeSignal timeSignal1 = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
-        TimestampedValue<Long> utcTime1 = timeSignal1.getUtcTime();
+        PhoneTimeSuggestion timeSuggestion1 =
+                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
+        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
 
         final int clockIncrement = 100;
         // Increment the the device clocks to simulate the passage of time.
@@ -86,7 +90,7 @@
                 TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
 
         // Send the first time signal. It should be used.
-        mScript.simulateTimeSignalReceived(timeSignal1)
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
                 .verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis1);
 
         // Now send another time signal, but one that is too similar to the last one and should be
@@ -95,9 +99,9 @@
         TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
                 mScript.peekElapsedRealtimeMillis(),
                 mScript.peekSystemClockMillis() + underThresholdMillis);
-        TimeSignal timeSignal2 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime2);
+        PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
         mScript.simulateTimePassing(clockIncrement)
-                .simulateTimeSignalReceived(timeSignal2)
+                .simulatePhoneTimeSuggestion(timeSuggestion2)
                 .verifySystemClockWasNotSetAndResetCallTracking();
 
         // Now send another time signal, but one that is on the threshold and so should be used.
@@ -105,42 +109,44 @@
                 mScript.peekElapsedRealtimeMillis(),
                 mScript.peekSystemClockMillis() + systemClockUpdateThresholdMillis);
 
-        TimeSignal timeSignal3 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime3);
+        PhoneTimeSuggestion timeSuggestion3 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
         mScript.simulateTimePassing(clockIncrement);
 
         long expectSystemClockMillis3 =
                 TimeDetectorStrategy.getTimeAt(utcTime3, mScript.peekElapsedRealtimeMillis());
 
-        mScript.simulateTimeSignalReceived(timeSignal3)
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
                 .verifySystemClockWasSetAndResetCallTracking(expectSystemClockMillis3);
     }
 
     @Test
-    public void testSuggestTime_nitz_timeDetectionDisabled() {
+    public void testSuggestPhoneTime_nitz_timeDetectionDisabled() {
         Scenario scenario = SCENARIO_1;
         mScript.pokeFakeClocks(scenario)
                 .pokeTimeDetectionEnabled(false);
 
-        TimeSignal timeSignal = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
-        mScript.simulateTimeSignalReceived(timeSignal)
+        PhoneTimeSuggestion timeSuggestion =
+                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion)
                 .verifySystemClockWasNotSetAndResetCallTracking();
     }
 
     @Test
-    public void testSuggestTime_nitz_invalidNitzReferenceTimesIgnored() {
+    public void testSuggestPhoneTime_nitz_invalidNitzReferenceTimesIgnored() {
         Scenario scenario = SCENARIO_1;
         final int systemClockUpdateThreshold = 2000;
         mScript.pokeFakeClocks(scenario)
                 .pokeThresholds(systemClockUpdateThreshold)
                 .pokeTimeDetectionEnabled(true);
-        TimeSignal timeSignal1 = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
-        TimestampedValue<Long> utcTime1 = timeSignal1.getUtcTime();
+        PhoneTimeSuggestion timeSuggestion1 =
+                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
+        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
 
         // Initialize the strategy / device with a time set from NITZ.
         mScript.simulateTimePassing(100);
         long expectedSystemClockMillis1 =
                 TimeDetectorStrategy.getTimeAt(utcTime1, mScript.peekElapsedRealtimeMillis());
-        mScript.simulateTimeSignalReceived(timeSignal1)
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
                 .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1);
 
         // The UTC time increment should be larger than the system clock update threshold so we
@@ -152,8 +158,8 @@
         long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
         TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
                 referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
-        TimeSignal timeSignal2 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime2);
-        mScript.simulateTimeSignalReceived(timeSignal2)
+        PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
                 .verifySystemClockWasNotSetAndResetCallTracking();
 
         // Now supply a new signal that has an obviously bogus reference time : substantially in the
@@ -162,8 +168,8 @@
                 utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
         TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
                 referenceTimeInFutureMillis, validUtcTimeMillis);
-        TimeSignal timeSignal3 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime3);
-        mScript.simulateTimeSignalReceived(timeSignal3)
+        PhoneTimeSuggestion timeSuggestion3 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime3);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion3)
                 .verifySystemClockWasNotSetAndResetCallTracking();
 
         // Just to prove validUtcTimeMillis is valid.
@@ -172,13 +178,13 @@
                 validReferenceTimeMillis, validUtcTimeMillis);
         long expectedSystemClockMillis4 =
                 TimeDetectorStrategy.getTimeAt(utcTime4, mScript.peekElapsedRealtimeMillis());
-        TimeSignal timeSignal4 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime4);
-        mScript.simulateTimeSignalReceived(timeSignal4)
+        PhoneTimeSuggestion timeSuggestion4 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime4);
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion4)
                 .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4);
     }
 
     @Test
-    public void testSuggestTime_timeDetectionToggled() {
+    public void testSuggestPhoneTime_timeDetectionToggled() {
         Scenario scenario = SCENARIO_1;
         final int clockIncrementMillis = 100;
         final int systemClockUpdateThreshold = 2000;
@@ -186,15 +192,16 @@
                 .pokeThresholds(systemClockUpdateThreshold)
                 .pokeTimeDetectionEnabled(false);
 
-        TimeSignal timeSignal1 = scenario.createTimeSignalForActual(TimeSignal.SOURCE_ID_NITZ);
-        TimestampedValue<Long> utcTime1 = timeSignal1.getUtcTime();
+        PhoneTimeSuggestion timeSuggestion1 =
+                scenario.createPhoneTimeSuggestionForActual(ARBITRARY_PHONE_ID);
+        TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
 
         // Simulate time passing.
         mScript.simulateTimePassing(clockIncrementMillis);
 
         // Simulate the time signal being received. It should not be used because auto time
         // detection is off but it should be recorded.
-        mScript.simulateTimeSignalReceived(timeSignal1)
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion1)
                 .verifySystemClockWasNotSetAndResetCallTracking();
 
         // Simulate more time passing.
@@ -216,7 +223,7 @@
         TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
                 mScript.peekElapsedRealtimeMillis(),
                 mScript.peekSystemClockMillis() + systemClockUpdateThreshold);
-        TimeSignal timeSignal2 = new TimeSignal(TimeSignal.SOURCE_ID_NITZ, utcTime2);
+        PhoneTimeSuggestion timeSuggestion2 = new PhoneTimeSuggestion(ARBITRARY_PHONE_ID, utcTime2);
 
         // Simulate more time passing.
         mScript.simulateTimePassing(clockIncrementMillis);
@@ -226,7 +233,7 @@
 
         // The new time, though valid, should not be set in the system clock because auto time is
         // disabled.
-        mScript.simulateTimeSignalReceived(timeSignal2)
+        mScript.simulatePhoneTimeSuggestion(timeSuggestion2)
                 .verifySystemClockWasNotSetAndResetCallTracking();
 
         // Turn on auto time detection.
@@ -234,17 +241,6 @@
                 .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2);
     }
 
-    @Test
-    public void testSuggestTime_unknownSource() {
-        Scenario scenario = SCENARIO_1;
-        mScript.pokeFakeClocks(scenario)
-                .pokeTimeDetectionEnabled(true);
-
-        TimeSignal timeSignal = scenario.createTimeSignalForActual("unknown");
-        mScript.simulateTimeSignalReceived(timeSignal)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-    }
-
     /**
      * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
      * like the real thing should, it also asserts preconditions.
@@ -407,8 +403,8 @@
             return mFakeCallback.peekSystemClockMillis();
         }
 
-        Script simulateTimeSignalReceived(TimeSignal timeSignal) {
-            mSimpleTimeDetectorStrategy.suggestTime(timeSignal);
+        Script simulatePhoneTimeSuggestion(PhoneTimeSuggestion timeSuggestion) {
+            mSimpleTimeDetectorStrategy.suggestPhoneTime(timeSuggestion);
             return this;
         }
 
@@ -466,10 +462,10 @@
             return mActualTimeMillis;
         }
 
-        TimeSignal createTimeSignalForActual(String sourceId) {
+        PhoneTimeSuggestion createPhoneTimeSuggestionForActual(int phoneId) {
             TimestampedValue<Long> time = new TimestampedValue<>(
                     mInitialDeviceRealtimeMillis, mActualTimeMillis);
-            return new TimeSignal(sourceId, time);
+            return new PhoneTimeSuggestion(phoneId, time);
         }
 
         static class Builder {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 45fef76..37da018 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -28,7 +28,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.timedetector.TimeSignal;
+import android.app.timedetector.PhoneTimeSuggestion;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.util.TimestampedValue;
@@ -67,10 +67,10 @@
     public void testStubbedCall_withoutPermission() {
         doThrow(new SecurityException("Mock"))
                 .when(mMockContext).enforceCallingPermission(anyString(), any());
-        TimeSignal timeSignal = createNitzTimeSignal();
+        PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
 
         try {
-            mTimeDetectorService.suggestTime(timeSignal);
+            mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
         } finally {
             verify(mMockContext).enforceCallingPermission(
                     eq(android.Manifest.permission.SET_TIME), anyString());
@@ -78,15 +78,15 @@
     }
 
     @Test
-    public void testSuggestTime() {
+    public void testSuggestPhoneTime() {
         doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
 
-        TimeSignal timeSignal = createNitzTimeSignal();
-        mTimeDetectorService.suggestTime(timeSignal);
+        PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
+        mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
 
         verify(mMockContext)
                 .enforceCallingPermission(eq(android.Manifest.permission.SET_TIME), anyString());
-        mStubbedTimeDetectorStrategy.verifySuggestTimeCalled(timeSignal);
+        mStubbedTimeDetectorStrategy.verifySuggestPhoneTimeCalled(phoneTimeSuggestion);
     }
 
     @Test
@@ -115,15 +115,16 @@
         mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionToggleCalled(false);
     }
 
-    private static TimeSignal createNitzTimeSignal() {
+    private static PhoneTimeSuggestion createPhoneTimeSuggestion() {
+        int phoneId = 1234;
         TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
-        return new TimeSignal(TimeSignal.SOURCE_ID_NITZ, timeValue);
+        return new PhoneTimeSuggestion(phoneId, timeValue);
     }
 
     private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
 
         // Call tracking.
-        private TimeSignal mLastSuggestedTime;
+        private PhoneTimeSuggestion mLastPhoneSuggestion;
         private Boolean mLastAutoTimeDetectionToggle;
         private boolean mDumpCalled;
 
@@ -132,9 +133,9 @@
         }
 
         @Override
-        public void suggestTime(TimeSignal timeSignal) {
+        public void suggestPhoneTime(PhoneTimeSuggestion timeSuggestion) {
             resetCallTracking();
-            mLastSuggestedTime = timeSignal;
+            mLastPhoneSuggestion = timeSuggestion;
         }
 
         @Override
@@ -150,13 +151,13 @@
         }
 
         void resetCallTracking() {
-            mLastSuggestedTime = null;
+            mLastPhoneSuggestion = null;
             mLastAutoTimeDetectionToggle = null;
             mDumpCalled = false;
         }
 
-        void verifySuggestTimeCalled(TimeSignal expectedSignal) {
-            assertEquals(expectedSignal, mLastSuggestedTime);
+        void verifySuggestPhoneTimeCalled(PhoneTimeSuggestion expectedSignal) {
+            assertEquals(expectedSignal, mLastPhoneSuggestion);
         }
 
         void verifyHandleAutoTimeDetectionToggleCalled(boolean expectedEnable) {
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 4ffcf8f..12ba219 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -47,7 +47,6 @@
 
 import android.app.usage.AppStandbyInfo;
 import android.app.usage.UsageEvents;
-import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -77,7 +76,6 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -108,8 +106,6 @@
     private static final long WORKING_SET_THRESHOLD = 12 * HOUR_MS;
     private static final long FREQUENT_THRESHOLD = 24 * HOUR_MS;
     private static final long RARE_THRESHOLD = 48 * HOUR_MS;
-    // Short STABLE_CHARGING_THRESHOLD for testing purposes
-    private static final long STABLE_CHARGING_THRESHOLD = 2000;
 
     /** Mock variable used in {@link MyInjector#isPackageInstalled(String, int, int)} */
     private static boolean isPackageInstalled = true;
@@ -132,7 +128,6 @@
     static class MyInjector extends AppStandbyController.Injector {
         long mElapsedRealtime;
         boolean mIsAppIdleEnabled = true;
-        boolean mIsCharging;
         List<String> mPowerSaveWhitelistExceptIdle = new ArrayList<>();
         boolean mDisplayOn;
         DisplayManager.DisplayListener mDisplayListener;
@@ -167,11 +162,6 @@
         }
 
         @Override
-        boolean isCharging() {
-            return mIsCharging;
-        }
-
-        @Override
         boolean isPowerSaveWhitelistExceptIdleApp(String packageName) throws RemoteException {
             return mPowerSaveWhitelistExceptIdle.contains(packageName);
         }
@@ -228,8 +218,7 @@
             return "screen_thresholds=0/0/0/" + HOUR_MS + ",elapsed_thresholds=0/"
                     + WORKING_SET_THRESHOLD + "/"
                     + FREQUENT_THRESHOLD + "/"
-                    + RARE_THRESHOLD + ","
-                    + "stable_charging_threshold=" + STABLE_CHARGING_THRESHOLD;
+                    + RARE_THRESHOLD;
         }
 
         @Override
@@ -273,13 +262,6 @@
         } catch (PackageManager.NameNotFoundException nnfe) {}
     }
 
-    private void setChargingState(AppStandbyController controller, boolean charging) {
-        mInjector.mIsCharging = charging;
-        if (controller != null) {
-            controller.setChargingState(charging);
-        }
-    }
-
     private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) {
         mInjector.mIsAppIdleEnabled = enabled;
         if (controller != null) {
@@ -296,7 +278,6 @@
         controller.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
         mInjector.setDisplayOn(false);
         mInjector.setDisplayOn(true);
-        setChargingState(controller, false);
         controller.checkIdleStates(USER_ID);
         assertNotEquals(STANDBY_BUCKET_EXEMPTED,
                 controller.getAppStandbyBucket(PACKAGE_1, USER_ID,
@@ -314,65 +295,6 @@
         MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext());
         mInjector = new MyInjector(myContext, Looper.getMainLooper());
         mController = setupController();
-        setChargingState(mController, false);
-    }
-
-    private class TestParoleListener extends UsageStatsManagerInternal.AppIdleStateChangeListener {
-        private boolean mOnParole = false;
-        private CountDownLatch mLatch;
-        private long mLastParoleChangeTime;
-        private boolean mIsExpecting = false;
-        private boolean mExpectedParoleState;
-
-        public boolean getParoleState() {
-            synchronized (this) {
-                return mOnParole;
-            }
-        }
-
-        public void rearmLatch() {
-            synchronized (this) {
-                mLatch = new CountDownLatch(1);
-                mIsExpecting = false;
-            }
-        }
-
-        public void rearmLatch(boolean expectedParoleState) {
-            synchronized (this) {
-                mLatch = new CountDownLatch(1);
-                mIsExpecting = true;
-                mExpectedParoleState = expectedParoleState;
-            }
-        }
-
-        public void awaitOnLatch(long time) throws Exception {
-            mLatch.await(time, TimeUnit.MILLISECONDS);
-        }
-
-        public long getLastParoleChangeTime() {
-            synchronized (this) {
-                return mLastParoleChangeTime;
-            }
-        }
-
-        @Override
-        public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
-                int bucket, int reason) {
-        }
-
-        @Override
-        public void onParoleStateChanged(boolean isParoleOn) {
-            synchronized (this) {
-                // Only record information if it is being looked for
-                if (mLatch != null && mLatch.getCount() > 0) {
-                    mOnParole = isParoleOn;
-                    mLastParoleChangeTime = getCurrentTime();
-                    if (!mIsExpecting || isParoleOn == mExpectedParoleState) {
-                        mLatch.countDown();
-                    }
-                }
-            }
-        }
     }
 
     @Test
@@ -383,133 +305,6 @@
                         mInjector.mElapsedRealtime, false));
     }
 
-    @Test
-    public void testCharging() throws Exception {
-        long startTime;
-        TestParoleListener paroleListener = new TestParoleListener();
-        long marginOfError = 200;
-
-        // Charging
-        paroleListener.rearmLatch();
-        mController.addListener(paroleListener);
-        startTime = getCurrentTime();
-        setChargingState(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        // Parole will only be granted after device has been charging for a sufficient amount of
-        // time.
-        assertEquals(STABLE_CHARGING_THRESHOLD,
-                paroleListener.getLastParoleChangeTime() - startTime,
-                marginOfError);
-
-        // Discharging
-        paroleListener.rearmLatch();
-        startTime = getCurrentTime();
-        setChargingState(mController, false);
-        mController.checkIdleStates(USER_ID);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.getParoleState());
-        // Parole should be revoked immediately
-        assertEquals(0,
-                paroleListener.getLastParoleChangeTime() - startTime,
-                marginOfError);
-
-        // Brief Charging
-        paroleListener.rearmLatch();
-        setChargingState(mController, true);
-        setChargingState(mController, false);
-        // Device stopped charging before the stable charging threshold.
-        // Parole should not be granted at the end of the threshold
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.getParoleState());
-
-        // Charging Again
-        paroleListener.rearmLatch();
-        startTime = getCurrentTime();
-        setChargingState(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.getParoleState());
-        assertTrue(paroleListener.mOnParole);
-        assertEquals(STABLE_CHARGING_THRESHOLD,
-                paroleListener.getLastParoleChangeTime() - startTime,
-                marginOfError);
-    }
-
-    @Test
-    public void testEnabledState() throws Exception {
-        TestParoleListener paroleListener = new TestParoleListener();
-        paroleListener.rearmLatch(true);
-        mController.addListener(paroleListener);
-        long lastUpdateTime;
-
-        // Test that listeners are notified if enabled changes when the device is not in parole.
-        setChargingState(mController, false);
-
-        // Start off not enabled. Device is effectively in permanent parole.
-        setAppIdleEnabled(mController, false);
-        // Since AppStandbyController uses a handler to notify listeners of a state change, there is
-        // some inherent latency between changing the state and getting the notification. We need to
-        // wait until the paroleListener has been notified that parole is on before continuing with
-        // the test.
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-
-        // Enable controller
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.mOnParole);
-        lastUpdateTime = paroleListener.getLastParoleChangeTime();
-
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertFalse(paroleListener.mOnParole);
-        // Make sure AppStandbyController doesn't notify listeners when there's no change.
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-
-        // Disable controller
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        lastUpdateTime = paroleListener.getLastParoleChangeTime();
-
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        // Make sure AppStandbyController doesn't notify listeners when there's no change.
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-
-
-        // Test that listeners aren't notified if enabled status changes when the device is already
-        // in parole.
-
-        // A device is in parole whenever it's charging.
-        setChargingState(mController, true);
-
-        // Start off not enabled.
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        lastUpdateTime = paroleListener.getLastParoleChangeTime();
-
-        // Test that toggling doesn't notify the listener.
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, true);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-
-        paroleListener.rearmLatch();
-        setAppIdleEnabled(mController, false);
-        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
-        assertTrue(paroleListener.mOnParole);
-        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
-    }
-
     private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
         mInjector.mElapsedRealtime = elapsedTime;
         controller.checkIdleStates(USER_ID);
@@ -804,8 +599,6 @@
 
     @Test
     public void testSystemInteractionTimeout() throws Exception {
-        setChargingState(mController, false);
-
         reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
         // Fast forward to RARE
         mInjector.mElapsedRealtime = RARE_THRESHOLD + 100;
@@ -829,8 +622,6 @@
 
     @Test
     public void testInitialForegroundServiceTimeout() throws Exception {
-        setChargingState(mController, false);
-
         mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
         // Make sure app is in NEVER bucket
         mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
diff --git a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
new file mode 100644
index 0000000..f1b2ef8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
@@ -0,0 +1,191 @@
+/*
+ * 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.usage;
+
+import static android.app.usage.UsageEvents.Event.MAX_EVENT_TYPE;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import android.app.usage.UsageEvents;
+import android.content.res.Configuration;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IntervalStatsTests {
+    private static final int NUMBER_OF_PACKAGES = 7;
+    private static final int NUMBER_OF_EVENTS_PER_PACKAGE = 200;
+    private static final int NUMBER_OF_EVENTS = NUMBER_OF_PACKAGES * NUMBER_OF_EVENTS_PER_PACKAGE;
+
+    private long mEndTime = 0;
+
+    private void populateIntervalStats(IntervalStats intervalStats) {
+        final int timeProgression = 23;
+        long time = System.currentTimeMillis() - (NUMBER_OF_EVENTS * timeProgression);
+
+        intervalStats.majorVersion = 7;
+        intervalStats.minorVersion = 8;
+        intervalStats.beginTime = time;
+        intervalStats.interactiveTracker.count = 2;
+        intervalStats.interactiveTracker.duration = 111111;
+        intervalStats.nonInteractiveTracker.count = 3;
+        intervalStats.nonInteractiveTracker.duration = 222222;
+        intervalStats.keyguardShownTracker.count = 4;
+        intervalStats.keyguardShownTracker.duration = 333333;
+        intervalStats.keyguardHiddenTracker.count = 5;
+        intervalStats.keyguardHiddenTracker.duration = 4444444;
+
+        for (int i = 0; i < NUMBER_OF_EVENTS; i++) {
+            UsageEvents.Event event = new UsageEvents.Event();
+            final int packageInt = ((i / 3) % NUMBER_OF_PACKAGES); // clusters of 3 events
+            event.mPackage = "fake.package.name" + packageInt;
+            if (packageInt == 3) {
+                // Third app is an instant app
+                event.mFlags |= UsageEvents.Event.FLAG_IS_PACKAGE_INSTANT_APP;
+            }
+
+            final int instanceId = i % 11;
+            event.mClass = ".fake.class.name" + instanceId;
+            event.mTimeStamp = time;
+            event.mEventType = i % (MAX_EVENT_TYPE + 1); //"random" event type
+            event.mInstanceId = instanceId;
+
+
+            final int rootPackageInt = (i % 5); // 5 "apps" start each task
+            event.mTaskRootPackage = "fake.package.name" + rootPackageInt;
+
+            final int rootClassInt = i % 6;
+            event.mTaskRootClass = ".fake.class.name" + rootClassInt;
+
+            switch (event.mEventType) {
+                case UsageEvents.Event.CONFIGURATION_CHANGE:
+                    event.mConfiguration = new Configuration(); //empty config
+                    break;
+                case UsageEvents.Event.SHORTCUT_INVOCATION:
+                    event.mShortcutId = "shortcut" + (i % 8); //"random" shortcut
+                    break;
+                case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                    //"random" bucket and reason
+                    event.mBucketAndReason = (((i % 5 + 1) * 10) << 16) & (i % 5 + 1) << 8;
+                    break;
+                case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                    event.mNotificationChannelId = "channel" + (i % 5); //"random" channel
+                    break;
+            }
+
+            intervalStats.addEvent(event);
+            intervalStats.update(event.mPackage, event.mClass, event.mTimeStamp, event.mEventType,
+                    event.mInstanceId);
+
+            time += timeProgression; // Arbitrary progression of time
+        }
+        mEndTime = time;
+
+        final Configuration config1 = new Configuration();
+        config1.fontScale = 3.3f;
+        config1.mcc = 4;
+        intervalStats.getOrCreateConfigurationStats(config1);
+
+        final Configuration config2 = new Configuration();
+        config2.mnc = 5;
+        config2.setLocale(new Locale("en", "US"));
+        intervalStats.getOrCreateConfigurationStats(config2);
+
+        intervalStats.activeConfiguration = config2;
+    }
+
+    @Test
+    public void testObfuscation() {
+        final IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats);
+
+        final PackagesTokenData packagesTokenData = new PackagesTokenData();
+        intervalStats.obfuscateData(packagesTokenData);
+
+        // data is populated with 7 different "apps"
+        assertEquals(packagesTokenData.tokensToPackagesMap.size(), NUMBER_OF_PACKAGES);
+        assertEquals(packagesTokenData.packagesToTokensMap.size(), NUMBER_OF_PACKAGES);
+        assertEquals(packagesTokenData.counter, NUMBER_OF_PACKAGES + 1);
+
+        assertEquals(intervalStats.events.size(), NUMBER_OF_EVENTS);
+        assertEquals(intervalStats.packageStats.size(), NUMBER_OF_PACKAGES);
+    }
+
+    @Test
+    public void testDeobfuscation() {
+        final IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats);
+
+        final PackagesTokenData packagesTokenData = new PackagesTokenData();
+        intervalStats.obfuscateData(packagesTokenData);
+        intervalStats.deobfuscateData(packagesTokenData);
+
+        // ensure deobfuscation doesn't update any of the mappings data
+        assertEquals(packagesTokenData.tokensToPackagesMap.size(), NUMBER_OF_PACKAGES);
+        assertEquals(packagesTokenData.packagesToTokensMap.size(), NUMBER_OF_PACKAGES);
+        assertEquals(packagesTokenData.counter, NUMBER_OF_PACKAGES + 1);
+
+        // ensure deobfuscation didn't remove any events or usage stats
+        assertEquals(intervalStats.events.size(), NUMBER_OF_EVENTS);
+        assertEquals(intervalStats.packageStats.size(), NUMBER_OF_PACKAGES);
+    }
+
+    @Test
+    public void testBadDataOnDeobfuscation() {
+        final IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats);
+
+        final PackagesTokenData packagesTokenData = new PackagesTokenData();
+        intervalStats.obfuscateData(packagesTokenData);
+        intervalStats.packageStats.clear();
+
+        // remove the mapping for token 2
+        packagesTokenData.tokensToPackagesMap.remove(2);
+
+        intervalStats.deobfuscateData(packagesTokenData);
+        // deobfuscation should have removed all events mapped to package token 2
+        assertEquals(intervalStats.events.size(),
+                NUMBER_OF_EVENTS - NUMBER_OF_EVENTS_PER_PACKAGE - 1);
+        assertEquals(intervalStats.packageStats.size(), NUMBER_OF_PACKAGES - 1);
+    }
+
+    @Test
+    public void testBadPackageDataOnDeobfuscation() {
+        final IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats);
+
+        final PackagesTokenData packagesTokenData = new PackagesTokenData();
+        intervalStats.obfuscateData(packagesTokenData);
+        intervalStats.packageStats.clear();
+
+        // remove mapping number 2 within package 3 (random)
+        packagesTokenData.tokensToPackagesMap.valueAt(3).remove(2);
+
+        intervalStats.deobfuscateData(packagesTokenData);
+        // deobfuscation should not have removed all events for a package - however, it's possible
+        // that some events were removed because of how shortcut and notification events are handled
+        assertTrue(intervalStats.events.size() > NUMBER_OF_EVENTS - NUMBER_OF_EVENTS_PER_PACKAGE);
+        assertEquals(intervalStats.packageStats.size(), NUMBER_OF_PACKAGES);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index c55f459..df0c37a 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -48,7 +48,7 @@
 @SmallTest
 public class UsageStatsDatabaseTest {
 
-    private static final int MAX_TESTED_VERSION = 4;
+    private static final int MAX_TESTED_VERSION = 5;
     protected Context mContext;
     private UsageStatsDatabase mUsageStatsDatabase;
     private File mTestDir;
@@ -74,6 +74,7 @@
         mContext = InstrumentationRegistry.getTargetContext();
         mTestDir = new File(mContext.getFilesDir(), "UsageStatsDatabaseTest");
         mUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
+        mUsageStatsDatabase.readMappingsLocked();
         mUsageStatsDatabase.init(1);
         populateIntervalStats();
         clearUsageStatsFiles();
@@ -259,6 +260,24 @@
 
     void compareUsageEvent(Event e1, Event e2, int debugId, int minVersion) {
         switch (minVersion) {
+            case 5: // test fields added in version 5
+                assertEquals(e1.mPackageToken, e2.mPackageToken, "Usage event " + debugId);
+                assertEquals(e1.mClassToken, e2.mClassToken, "Usage event " + debugId);
+                assertEquals(e1.mTaskRootPackageToken, e2.mTaskRootPackageToken,
+                        "Usage event " + debugId);
+                assertEquals(e1.mTaskRootClassToken, e2.mTaskRootClassToken,
+                        "Usage event " + debugId);
+                switch (e1.mEventType) {
+                    case Event.SHORTCUT_INVOCATION:
+                        assertEquals(e1.mShortcutIdToken, e2.mShortcutIdToken,
+                                "Usage event " + debugId);
+                        break;
+                    case Event.NOTIFICATION_INTERRUPTION:
+                        assertEquals(e1.mNotificationChannelIdToken, e2.mNotificationChannelIdToken,
+                                "Usage event " + debugId);
+                        break;
+                }
+                // fallthrough
             case 4: // test fields added in version 4
                 assertEquals(e1.mInstanceId, e2.mInstanceId, "Usage event " + debugId);
                 assertEquals(e1.mTaskRootPackage, e2.mTaskRootPackage, "Usage event " + debugId);
@@ -370,11 +389,16 @@
     void runVersionChangeTest(int oldVersion, int newVersion, int interval) throws IOException {
         // Write IntervalStats to disk in old version format
         UsageStatsDatabase prevDB = new UsageStatsDatabase(mTestDir, oldVersion);
+        prevDB.readMappingsLocked();
         prevDB.init(1);
         prevDB.putUsageStats(interval, mIntervalStats);
+        if (oldVersion >= 5) {
+            prevDB.writeMappingsLocked();
+        }
 
         // Simulate an upgrade to a new version and read from the disk
         UsageStatsDatabase newDB = new UsageStatsDatabase(mTestDir, newVersion);
+        newDB.readMappingsLocked();
         newDB.init(mEndTime);
         List<IntervalStats> stats = newDB.queryUsageStats(interval, 0, mEndTime,
                 mIntervalStatsVerifier);
@@ -394,6 +418,7 @@
      */
     void runBackupRestoreTest(int version) throws IOException {
         UsageStatsDatabase prevDB = new UsageStatsDatabase(mTestDir);
+        prevDB.readMappingsLocked();
         prevDB.init(1);
         prevDB.putUsageStats(UsageStatsManager.INTERVAL_DAILY, mIntervalStats);
         // Create a backup with a specific version
@@ -402,6 +427,7 @@
         clearUsageStatsFiles();
 
         UsageStatsDatabase newDB = new UsageStatsDatabase(mTestDir);
+        newDB.readMappingsLocked();
         newDB.init(1);
         // Attempt to restore the usage stats from the backup
         newDB.applyRestoredPayload(KEY_USAGE_STATS, blob);
@@ -438,6 +464,28 @@
         runVersionChangeTest(3, 4, UsageStatsManager.INTERVAL_YEARLY);
     }
 
+    /**
+     * Test the version upgrade from 4 to 5
+     */
+    @Test
+    public void testVersionUpgradeFrom4to5() throws IOException {
+        runVersionChangeTest(4, 5, UsageStatsManager.INTERVAL_DAILY);
+        runVersionChangeTest(4, 5, UsageStatsManager.INTERVAL_WEEKLY);
+        runVersionChangeTest(4, 5, UsageStatsManager.INTERVAL_MONTHLY);
+        runVersionChangeTest(4, 5, UsageStatsManager.INTERVAL_YEARLY);
+    }
+
+    /**
+     * Test the version upgrade from 3 to 5
+     */
+    @Test
+    public void testVersionUpgradeFrom3to5() throws IOException {
+        runVersionChangeTest(3, 5, UsageStatsManager.INTERVAL_DAILY);
+        runVersionChangeTest(3, 5, UsageStatsManager.INTERVAL_WEEKLY);
+        runVersionChangeTest(3, 5, UsageStatsManager.INTERVAL_MONTHLY);
+        runVersionChangeTest(3, 5, UsageStatsManager.INTERVAL_YEARLY);
+    }
+
 
     /**
      * Test the version upgrade from 3 to 4
@@ -492,4 +540,68 @@
             assertEquals(extra, files.keyAt(0));
         }
     }
+
+    private void compareObfuscatedData(int interval) throws IOException {
+        // Write IntervalStats to disk
+        UsageStatsDatabase prevDB = new UsageStatsDatabase(mTestDir, 5);
+        prevDB.readMappingsLocked();
+        prevDB.init(1);
+        prevDB.putUsageStats(interval, mIntervalStats);
+        prevDB.writeMappingsLocked();
+
+        // Read IntervalStats from disk into a new db
+        UsageStatsDatabase newDB = new UsageStatsDatabase(mTestDir, 5);
+        newDB.readMappingsLocked();
+        newDB.init(mEndTime);
+        List<IntervalStats> stats = newDB.queryUsageStats(interval, 0, mEndTime,
+                mIntervalStatsVerifier);
+
+        assertEquals(1, stats.size());
+        // The written and read IntervalStats should match
+        compareIntervalStats(mIntervalStats, stats.get(0), 5);
+    }
+
+    @Test
+    public void testObfuscation() throws IOException {
+        compareObfuscatedData(UsageStatsManager.INTERVAL_DAILY);
+        compareObfuscatedData(UsageStatsManager.INTERVAL_WEEKLY);
+        compareObfuscatedData(UsageStatsManager.INTERVAL_MONTHLY);
+        compareObfuscatedData(UsageStatsManager.INTERVAL_YEARLY);
+    }
+
+    private void verifyPackageNotRetained(int interval) throws IOException {
+        UsageStatsDatabase db = new UsageStatsDatabase(mTestDir, 5);
+        db.readMappingsLocked();
+        db.init(1);
+        db.putUsageStats(interval, mIntervalStats);
+
+        final String removedPackage = "fake.package.name0";
+        // invoke handler call directly from test to remove package
+        db.onPackageRemoved(removedPackage, System.currentTimeMillis());
+
+        List<IntervalStats> stats = db.queryUsageStats(interval, 0, mEndTime,
+                mIntervalStatsVerifier);
+        for (int i = 0; i < stats.size(); i++) {
+            final IntervalStats stat = stats.get(i);
+            if (stat.packageStats.containsKey(removedPackage)) {
+                fail("Found removed package " + removedPackage + " in package stats.");
+                return;
+            }
+            for (int j = 0; j < stat.events.size(); j++) {
+                final Event event = stat.events.get(j);
+                if (removedPackage.equals(event.mPackage)) {
+                    fail("Found an event from removed package " + removedPackage);
+                    return;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testPackageRetention() throws IOException {
+        verifyPackageNotRetained(UsageStatsManager.INTERVAL_DAILY);
+        verifyPackageNotRetained(UsageStatsManager.INTERVAL_WEEKLY);
+        verifyPackageNotRetained(UsageStatsManager.INTERVAL_MONTHLY);
+        verifyPackageNotRetained(UsageStatsManager.INTERVAL_YEARLY);
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 3ae5674..1e55b15 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -22,6 +22,7 @@
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.media.AudioAttributes.USAGE_NOTIFICATION;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
 
 import static junit.framework.Assert.assertFalse;
@@ -1541,10 +1542,12 @@
     }
 
     @Test
-    public void testCanInterruptNonRingtoneInsistentBuzz() throws Exception {
+    public void testCanInterruptNonRingtoneInsistentBuzz() {
         NotificationChannel fakeRingtoneChannel =
                 new NotificationChannel("ringtone", "", IMPORTANCE_HIGH);
         fakeRingtoneChannel.enableVibration(true);
+        fakeRingtoneChannel.setSound(null,
+                new AudioAttributes.Builder().setUsage(USAGE_NOTIFICATION).build());
         NotificationRecord ringtoneNotification = getCallRecord(1, fakeRingtoneChannel, true);
 
         mService.buzzBeepBlinkLocked(ringtoneNotification);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 2836e69..03367db 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -18,8 +18,6 @@
 
 import static android.app.ActivityManager.START_SUCCESS;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -63,10 +61,8 @@
     private ActivityMetricsLaunchObserver mLaunchObserver;
     private ActivityMetricsLaunchObserverRegistry mLaunchObserverRegistry;
 
-    private ActivityStack mStack;
-    private TaskRecord mTask;
-    private ActivityRecord mActivityRecord;
-    private ActivityRecord mActivityRecordTrampoline;
+    private ActivityRecord mTrampolineActivity;
+    private ActivityRecord mTopActivity;
 
     @Before
     public void setUpAMLO() {
@@ -80,15 +76,10 @@
 
         // Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
         // This seems to be the easiest way to create an ActivityRecord.
-        mStack = new StackBuilder(mRootActivityContainer)
-                .setActivityType(ACTIVITY_TYPE_STANDARD)
-                .setWindowingMode(WINDOWING_MODE_FULLSCREEN)
-                .setOnTop(true)
-                .setCreateActivity(true)
+        mTrampolineActivity = new ActivityBuilder(mService).setCreateTask(true).build();
+        mTopActivity = new ActivityBuilder(mService)
+                .setTask(mTrampolineActivity.getTaskRecord())
                 .build();
-        mTask = mStack.topTask();
-        mActivityRecord = mTask.getTopActivity();
-        mActivityRecordTrampoline = new ActivityBuilder(mService).setTask(mTask).build();
     }
 
     @After
@@ -123,8 +114,7 @@
         return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5)));
     }
 
-    @Test
-    public void testOnIntentStarted() throws Exception {
+    private void onIntentStarted() {
         Intent intent = new Intent("action 1");
 
         mActivityMetricsLogger.notifyActivityLaunching(intent);
@@ -134,123 +124,120 @@
     }
 
     @Test
-    public void testOnIntentFailed() throws Exception {
-        testOnIntentStarted();
-
-        ActivityRecord activityRecord = null;
+    public void testOnIntentFailed() {
+        onIntentStarted();
 
         // Bringing an intent that's already running 'to front' is not considered
         // as an ACTIVITY_LAUNCHED state transition.
         mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
-                activityRecord);
+                null /* launchedActivity */);
 
         verifyAsync(mLaunchObserver).onIntentFailed();
         verifyNoMoreInteractions(mLaunchObserver);
     }
 
-    @Test
-    public void testOnActivityLaunched() throws Exception {
-        testOnIntentStarted();
+    private void onActivityLaunched() {
+        onIntentStarted();
 
-        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
-                mActivityRecord);
+        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTopActivity);
 
-        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mActivityRecord), anyInt());
+        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt());
         verifyNoMoreInteractions(mLaunchObserver);
     }
 
     @Test
-    public void testOnActivityLaunchFinished() throws Exception {
-       testOnActivityLaunched();
+    public void testOnActivityLaunchFinished() {
+        onActivityLaunched();
 
-       mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
-               SystemClock.elapsedRealtimeNanos());
+        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
+                SystemClock.elapsedRealtimeNanos());
 
-       mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecord.getWindowingMode(),
-               SystemClock.elapsedRealtimeNanos());
+        notifyWindowsDrawn(mTopActivity);
 
-       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecord), anyLong());
-       verifyNoMoreInteractions(mLaunchObserver);
-    }
-
-    @Test
-    public void testOnActivityLaunchCancelled() throws Exception {
-       testOnActivityLaunched();
-
-       mActivityRecord.mDrawn = true;
-
-       // Cannot time already-visible activities.
-       mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mActivityRecord);
-
-       verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mActivityRecord));
-       verifyNoMoreInteractions(mLaunchObserver);
-    }
-
-    @Test
-    public void testOnReportFullyDrawn() throws Exception {
-        testOnActivityLaunched();
-
-        mActivityMetricsLogger.logAppTransitionReportedDrawn(mActivityRecord, false);
-
-        verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mActivityRecord), anyLong());
+        verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
         verifyNoMoreInteractions(mLaunchObserver);
     }
 
     @Test
-    public void testOnActivityLaunchedTrampoline() throws Exception {
-        testOnIntentStarted();
+    public void testOnActivityLaunchCancelled() {
+        onActivityLaunched();
 
-        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
-                mActivityRecord);
+        mTopActivity.mDrawn = true;
 
-        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mActivityRecord), anyInt());
+        // Cannot time already-visible activities.
+        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTopActivity);
+
+        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTopActivity));
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnReportFullyDrawn() {
+        onActivityLaunched();
+
+        mActivityMetricsLogger.logAppTransitionReportedDrawn(mTopActivity, false);
+
+        verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mTopActivity), anyLong());
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    private void onActivityLaunchedTrampoline() {
+        onIntentStarted();
+
+        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTopActivity);
+
+        verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt());
 
         // A second, distinct, activity launch is coalesced into the the current app launch sequence
-        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
-                mActivityRecordTrampoline);
+        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTrampolineActivity);
 
         verifyNoMoreInteractions(mLaunchObserver);
     }
 
-    @Test
-    public void testOnActivityLaunchFinishedTrampoline() throws Exception {
-       testOnActivityLaunchedTrampoline();
-
-       mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
-               SystemClock.elapsedRealtimeNanos());
-
-       mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecordTrampoline.getWindowingMode(),
-               SystemClock.elapsedRealtimeNanos());
-
-       verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecordTrampoline),
-                                                             anyLong());
-       verifyNoMoreInteractions(mLaunchObserver);
+    private void notifyWindowsDrawn(ActivityRecord r) {
+        mActivityMetricsLogger.notifyWindowsDrawn(r.getWindowingMode(),
+                SystemClock.elapsedRealtimeNanos());
     }
 
     @Test
-    public void testOnActivityLaunchCancelledTrampoline() throws Exception {
-       testOnActivityLaunchedTrampoline();
+    public void testOnActivityLaunchFinishedTrampoline() {
+        onActivityLaunchedTrampoline();
 
-       mActivityRecordTrampoline.mDrawn = true;
+        mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
+                SystemClock.elapsedRealtimeNanos());
 
-       // Cannot time already-visible activities.
-       mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
-               mActivityRecordTrampoline);
+        notifyWindowsDrawn(mTrampolineActivity);
 
-       verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mActivityRecordTrampoline));
-       verifyNoMoreInteractions(mLaunchObserver);
+        notifyWindowsDrawn(mTopActivity);
+
+        verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTrampolineActivity),
+                anyLong());
+        verifyNoMoreInteractions(mLaunchObserver);
     }
 
     @Test
-    public void testActivityRecordProtoIsNotTooBig() throws Exception {
+    public void testOnActivityLaunchCancelledTrampoline() {
+        onActivityLaunchedTrampoline();
+
+        mTrampolineActivity.mDrawn = true;
+
+        // Cannot time already-visible activities.
+        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTrampolineActivity);
+
+        verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity));
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testActivityRecordProtoIsNotTooBig() {
         // The ActivityRecordProto must not be too big, otherwise converting it at runtime
         // will become prohibitively expensive.
-        assertWithMessage("mActivityRecord: %s", mActivityRecord).
-                that(activityRecordToProto(mActivityRecord).length).
-                isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
+        assertWithMessage("mTopActivity: %s", mTopActivity)
+                .that(activityRecordToProto(mTopActivity).length)
+                .isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
 
-        assertWithMessage("mActivityRecordTrampoline: %s", mActivityRecordTrampoline).
-                that(activityRecordToProto(mActivityRecordTrampoline).length).
-                isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
+        assertWithMessage("mTrampolineActivity: %s", mTrampolineActivity)
+                .that(activityRecordToProto(mTrampolineActivity).length)
+                .isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
similarity index 69%
rename from services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
rename to services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
index 5cd649f..77f9f04 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
@@ -39,11 +39,11 @@
  * Tests for the {@link TaskStack} class.
  *
  * Build/Install/Run:
- *  atest FrameworksServicesTests:AnimatingAppWindowTokenRegistryTest
+ *  atest FrameworksServicesTests:AnimatingActivityRegistryTest
  */
 @SmallTest
 @Presubmit
-public class AnimatingAppWindowTokenRegistryTest extends WindowTestsBase {
+public class AnimatingActivityRegistryTest extends WindowTestsBase {
 
     @Mock
     AnimationAdapter mAdapter;
@@ -60,22 +60,22 @@
 
     @Test
     public void testDeferring() {
-        final AppWindowToken window1 = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity1 = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
-                "window2").mAppToken;
-        final AnimatingAppWindowTokenRegistry registry =
-                window1.getStack().getAnimatingAppWindowTokenRegistry();
+        final ActivityRecord activity2 = createAppWindow(activity1.getTask(), ACTIVITY_TYPE_STANDARD,
+                "activity2").mActivityRecord;
+        final AnimatingActivityRegistry registry =
+                activity1.getStack().getAnimatingActivityRegistry();
 
-        window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
-        window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
-        assertTrue(window1.isSelfAnimating());
-        assertTrue(window2.isSelfAnimating());
+        activity1.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */);
+        activity2.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */);
+        assertTrue(activity1.isSelfAnimating());
+        assertTrue(activity2.isSelfAnimating());
 
         // Make sure that first animation finish is deferred, second one is not deferred, and first
         // one gets cancelled.
-        assertTrue(registry.notifyAboutToFinish(window1, mMockEndDeferFinishCallback1));
-        assertFalse(registry.notifyAboutToFinish(window2, mMockEndDeferFinishCallback2));
+        assertTrue(registry.notifyAboutToFinish(activity1, mMockEndDeferFinishCallback1));
+        assertFalse(registry.notifyAboutToFinish(activity2, mMockEndDeferFinishCallback2));
         verify(mMockEndDeferFinishCallback1).run();
         verifyZeroInteractions(mMockEndDeferFinishCallback2);
     }
@@ -83,12 +83,12 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testContainerRemoved() {
-        final AppWindowToken window1 = createAppWindowToken(mDisplayContent,
+        final ActivityRecord window1 = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
-                "window2").mAppToken;
-        final AnimatingAppWindowTokenRegistry registry =
-                window1.getStack().getAnimatingAppWindowTokenRegistry();
+        final ActivityRecord window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
+                "window2").mActivityRecord;
+        final AnimatingActivityRegistry registry =
+                window1.getStack().getAnimatingActivityRegistry();
 
         window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
         window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index b174251..1fb6a56 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -57,14 +57,12 @@
 
     private TaskStack mStack;
     private Task mTask;
-    private ActivityRecord mToken;
+    private ActivityRecord mActivity;
 
     public void setUpOnDisplay(DisplayContent dc) {
-        mStack = createTaskStackOnDisplay(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, dc);
-        mTask = createTaskInStack(mStack, 0 /* userId */);
-        mToken = WindowTestUtils.createTestAppWindowToken(dc);
-
-        mTask.addChild(mToken, 0);
+        mActivity = createTestActivityRecord(dc, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
+        mTask = mActivity.getTask();
+        mStack = mTask.mStack;
 
         // Set a remote animator with snapshot disabled. Snapshots don't work in wmtests.
         RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
@@ -110,11 +108,11 @@
 
         // Verify we are in a change transition, but without a snapshot.
         // Though, the test will actually have crashed by now if a snapshot is attempted.
-        assertNull(mToken.getThumbnail());
-        assertTrue(mToken.isInChangeTransition());
+        assertNull(mActivity.getThumbnail());
+        assertTrue(mActivity.isInChangeTransition());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -125,16 +123,16 @@
 
         mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(1, mDisplayContent.mChangingApps.size());
-        assertTrue(mToken.isInChangeTransition());
+        assertTrue(mActivity.isInChangeTransition());
 
         // Removing the app-token from the display should clean-up the
         // the change leash.
-        mDisplayContent.removeAppToken(mToken.token);
+        mDisplayContent.removeAppToken(mActivity.token);
         assertEquals(0, mDisplayContent.mChangingApps.size());
-        assertFalse(mToken.isInChangeTransition());
+        assertFalse(mActivity.isInChangeTransition());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -155,11 +153,11 @@
         assertEquals(WINDOWING_MODE_FULLSCREEN, mTask.getWindowingMode());
 
         // Make sure we're not waiting for a change animation (no leash)
-        assertFalse(mToken.isInChangeTransition());
-        assertNull(mToken.getThumbnail());
+        assertFalse(mActivity.isInChangeTransition());
+        assertNull(mActivity.getThumbnail());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -167,16 +165,16 @@
         // setup currently defaults to no snapshot.
         setUpOnDisplay(mDisplayContent);
 
-        mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        mTask.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
         assertEquals(1, mDisplayContent.mChangingApps.size());
-        assertTrue(mToken.isInChangeTransition());
+        assertTrue(mActivity.isInChangeTransition());
 
         // Changing visibility should cancel the change transition and become closing
-        mToken.setVisibility(false, false);
+        mActivity.setVisibility(false, false);
         assertEquals(0, mDisplayContent.mChangingApps.size());
-        assertFalse(mToken.isInChangeTransition());
+        assertFalse(mActivity.isInChangeTransition());
 
         waitUntilHandlersIdle();
-        mToken.removeImmediately();
+        mActivity.removeImmediately();
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 14939cc..6020453 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -57,9 +57,9 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testTranslucentOpen() {
-        final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+        final ActivityRecord behind = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+        final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentOpening.setOccludesParent(false);
         translucentOpening.setHidden(true);
@@ -72,9 +72,9 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testTranslucentClose() {
-        final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+        final ActivityRecord behind = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken translucentClosing = createAppWindowToken(mDisplayContent,
+        final ActivityRecord translucentClosing = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentClosing.setOccludesParent(false);
         mDisplayContent.mClosingApps.add(translucentClosing);
@@ -85,9 +85,9 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testChangeIsNotOverwritten() {
-        final AppWindowToken behind = createAppWindowToken(mDisplayContent,
+        final ActivityRecord behind = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken translucentOpening = createAppWindowToken(mDisplayContent,
+        final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentOpening.setOccludesParent(false);
         translucentOpening.setHidden(true);
@@ -101,10 +101,10 @@
     @Test
     @FlakyTest(bugId = 131005232)
     public void testTransitWithinTask() {
-        final ActivityRecord opening = createAppWindowToken(mDisplayContent,
+        final ActivityRecord opening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
         opening.setOccludesParent(false);
-        final ActivityRecord closing = createAppWindowToken(mDisplayContent,
+        final ActivityRecord closing = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
         closing.setOccludesParent(false);
         final Task task = opening.getTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 9d53676..06afce2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -122,14 +122,14 @@
         final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
 
         // Create 2 app window tokens to represent 2 activity window.
-        final AppWindowToken token1 = createTestAppWindowToken(dc1,
+        final ActivityRecord activity1 = createTestActivityRecord(dc1,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken token2 = createTestAppWindowToken(dc2,
+        final ActivityRecord activity2 = createTestActivityRecord(dc2,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
 
-        token1.allDrawn = true;
-        token1.startingDisplayed = true;
-        token1.startingMoved = true;
+        activity1.allDrawn = true;
+        activity1.startingDisplayed = true;
+        activity1.startingMoved = true;
 
         // Simulate activity resume / finish flows to prepare app transition & set visibility,
         // make sure transition is set as expected for each display.
@@ -141,8 +141,8 @@
         assertEquals(TRANSIT_ACTIVITY_CLOSE, dc2.mAppTransition.getAppTransition());
         // One activity window is visible for resuming & the other activity window is invisible
         // for finishing in different display.
-        token1.setVisibility(true, false);
-        token2.setVisibility(false, false);
+        activity1.setVisibility(true, false);
+        activity2.setVisibility(false, false);
 
         // Make sure each display is in animating stage.
         assertTrue(dc1.mOpeningApps.size() > 0);
@@ -159,12 +159,12 @@
 
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
-        final ActivityRecord token1 =
-                WindowTestUtils.createTestAppWindowToken(dc1);
-        task1.addChild(token1, 0);
+        final ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(dc1);
+        task1.addChild(activity1, 0);
 
         // Simulate same app is during opening / closing transition set stage.
-        dc1.mClosingApps.add(token1);
+        dc1.mClosingApps.add(activity1);
         assertTrue(dc1.mClosingApps.size() > 0);
 
         dc1.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
@@ -172,15 +172,15 @@
         assertEquals(TRANSIT_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransition());
         assertTrue(dc1.mAppTransition.isTransitionSet());
 
-        dc1.mOpeningApps.add(token1);
+        dc1.mOpeningApps.add(activity1);
         assertTrue(dc1.mOpeningApps.size() > 0);
 
         // Move stack to another display.
         stack1.reparent(dc2.getDisplayId(),  new Rect(), true);
 
         // Verify if token are cleared from both pending transition list in former display.
-        assertFalse(dc1.mOpeningApps.contains(token1));
-        assertFalse(dc1.mOpeningApps.contains(token1));
+        assertFalse(dc1.mOpeningApps.contains(activity1));
+        assertFalse(dc1.mOpeningApps.contains(activity1));
     }
 
     @Test
@@ -197,7 +197,7 @@
         doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
         final WindowState exitingAppWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
                 dc, "exiting app");
-        final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+        final ActivityRecord exitingActivity= exitingAppWindow.mActivityRecord;
         // Wait until everything in animation handler get executed to prevent the exiting window
         // from being removed during WindowSurfacePlacer Traversal.
         waitUntilHandlersIdle();
@@ -215,7 +215,7 @@
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
         assertEquals(TRANSIT_ACTIVITY_CLOSE, dc.mAppTransition.getAppTransition());
         dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
-        exitingAppToken.setVisibility(false, false);
+        exitingActivity.setVisibility(false, false);
         assertTrue(dc.mClosingApps.size() > 0);
 
         // Make sure window is in animating stage before freeze, and cancel after freeze.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
index aacdeb2..8520d21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
@@ -47,10 +47,10 @@
     private AppWindowThumbnail buildThumbnail() {
         final GraphicBuffer buffer = GraphicBuffer.create(1, 1, PixelFormat.RGBA_8888,
                 GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
-        final AppWindowToken mockAwt = mock(AppWindowToken.class);
-        when(mockAwt.getPendingTransaction()).thenReturn(new StubTransaction());
-        when(mockAwt.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
-        return new AppWindowThumbnail(new StubTransaction(), mockAwt,
+        final ActivityRecord mockAr = mock(ActivityRecord.class);
+        when(mockAr.getPendingTransaction()).thenReturn(new StubTransaction());
+        when(mockAr.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
+        return new AppWindowThumbnail(new StubTransaction(), mockAr,
                 buffer, false, mock(Surface.class), mock(SurfaceAnimator.class));
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index 66ba81d..b0f3b42 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -42,7 +42,7 @@
 
 
 /**
- * Animation related tests for the {@link AppWindowToken} class.
+ * Animation related tests for the {@link ActivityRecord} class.
  *
  * Build/Install/Run:
  *  atest AppWindowTokenAnimationTests
@@ -52,7 +52,7 @@
 @RunWith(WindowTestRunner.class)
 public class AppWindowTokenAnimationTests extends WindowTestsBase {
 
-    private AppWindowToken mToken;
+    private ActivityRecord mActivity;
 
     @Mock
     private AnimationAdapter mSpec;
@@ -61,39 +61,39 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
+        mActivity = createTestActivityRecord(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD);
     }
 
     @Test
     @FlakyTest(bugId = 131005232)
     public void clipAfterAnim_boundsLayerIsCreated() {
-        mToken.mNeedsAnimationBoundsLayer = true;
+        mActivity.mNeedsAnimationBoundsLayer = true;
 
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        verify(mTransaction).reparent(eq(mToken.getSurfaceControl()),
-                eq(mToken.mSurfaceAnimator.mLeash));
-        verify(mTransaction).reparent(eq(mToken.mSurfaceAnimator.mLeash),
-                eq(mToken.mAnimationBoundsLayer));
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).reparent(eq(mActivity.getSurfaceControl()),
+                eq(mActivity.mSurfaceAnimator.mLeash));
+        verify(mTransaction).reparent(eq(mActivity.mSurfaceAnimator.mLeash),
+                eq(mActivity.mAnimationBoundsLayer));
     }
 
     @Test
     public void clipAfterAnim_boundsLayerZBoosted() {
-        mToken.mNeedsAnimationBoundsLayer = true;
-        mToken.mNeedsZBoost = true;
+        mActivity.mNeedsAnimationBoundsLayer = true;
+        mActivity.mNeedsZBoost = true;
 
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        verify(mTransaction).setLayer(eq(mToken.mAnimationBoundsLayer),
-                intThat(layer -> layer >= AppWindowToken.Z_BOOST_BASE));
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).setLayer(eq(mActivity.mAnimationBoundsLayer),
+                intThat(layer -> layer >= ActivityRecord.Z_BOOST_BASE));
     }
 
     @Test
     @FlakyTest(bugId = 131005232)
     public void clipAfterAnim_boundsLayerIsDestroyed() {
-        mToken.mNeedsAnimationBoundsLayer = true;
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash;
-        final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer;
+        mActivity.mNeedsAnimationBoundsLayer = true;
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        final SurfaceControl leash = mActivity.mSurfaceAnimator.mLeash;
+        final SurfaceControl animationBoundsLayer = mActivity.mAnimationBoundsLayer;
         final ArgumentCaptor<SurfaceAnimator.OnAnimationFinishedCallback> callbackCaptor =
                 ArgumentCaptor.forClass(
                         SurfaceAnimator.OnAnimationFinishedCallback.class);
@@ -102,30 +102,30 @@
         callbackCaptor.getValue().onAnimationFinished(mSpec);
         verify(mTransaction).remove(eq(leash));
         verify(mTransaction).remove(eq(animationBoundsLayer));
-        assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse();
+        assertThat(mActivity.mNeedsAnimationBoundsLayer).isFalse();
     }
 
     @Test
     public void clipAfterAnimCancelled_boundsLayerIsDestroyed() {
-        mToken.mNeedsAnimationBoundsLayer = true;
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash;
-        final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer;
+        mActivity.mNeedsAnimationBoundsLayer = true;
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        final SurfaceControl leash = mActivity.mSurfaceAnimator.mLeash;
+        final SurfaceControl animationBoundsLayer = mActivity.mAnimationBoundsLayer;
 
-        mToken.mSurfaceAnimator.cancelAnimation();
+        mActivity.mSurfaceAnimator.cancelAnimation();
         verify(mTransaction).remove(eq(leash));
         verify(mTransaction).remove(eq(animationBoundsLayer));
-        assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse();
+        assertThat(mActivity.mNeedsAnimationBoundsLayer).isFalse();
     }
 
     @Test
     @FlakyTest(bugId = 131005232)
     public void clipNoneAnim_boundsLayerIsNotCreated() {
-        mToken.mNeedsAnimationBoundsLayer = false;
+        mActivity.mNeedsAnimationBoundsLayer = false;
 
-        mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
-        verify(mTransaction).reparent(eq(mToken.getSurfaceControl()),
-                eq(mToken.mSurfaceAnimator.mLeash));
-        assertThat(mToken.mAnimationBoundsLayer).isNull();
+        mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
+        verify(mTransaction).reparent(eq(mActivity.getSurfaceControl()),
+                eq(mActivity.mSurfaceAnimator.mLeash));
+        assertThat(mActivity.mAnimationBoundsLayer).isNull();
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index b4c978f..d68aef0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -65,7 +65,7 @@
 import org.mockito.Mockito;
 
 /**
- * Tests for the {@link AppWindowToken} class.
+ * Tests for the {@link ActivityRecord} class.
  *
  * Build/Install/Run:
  *  atest WmTests:AppWindowTokenTests
@@ -77,7 +77,7 @@
 
     TaskStack mStack;
     Task mTask;
-    ActivityRecord mToken;
+    ActivityRecord mActivity;
 
     private final String mPackageName = getInstrumentation().getTargetContext().getPackageName();
 
@@ -85,68 +85,68 @@
     public void setUp() throws Exception {
         mStack = createTaskStackOnDisplay(mDisplayContent);
         mTask = createTaskInStack(mStack, 0 /* userId */);
-        mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+        mActivity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
 
-        mTask.addChild(mToken, 0);
+        mTask.addChild(mActivity, 0);
     }
 
     @Test
     @Presubmit
     public void testAddWindow_Order() {
-        assertEquals(0, mToken.getChildCount());
+        assertEquals(0, mActivity.getChildCount());
 
-        final WindowState win1 = createWindow(null, TYPE_APPLICATION, mToken, "win1");
-        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, mToken,
+        final WindowState win1 = createWindow(null, TYPE_APPLICATION, mActivity, "win1");
+        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, mActivity,
                 "startingWin");
-        final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, mToken, "baseWin");
-        final WindowState win4 = createWindow(null, TYPE_APPLICATION, mToken, "win4");
+        final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "baseWin");
+        final WindowState win4 = createWindow(null, TYPE_APPLICATION, mActivity, "win4");
 
         // Should not contain the windows that were added above.
-        assertEquals(4, mToken.getChildCount());
-        assertTrue(mToken.mChildren.contains(win1));
-        assertTrue(mToken.mChildren.contains(startingWin));
-        assertTrue(mToken.mChildren.contains(baseWin));
-        assertTrue(mToken.mChildren.contains(win4));
+        assertEquals(4, mActivity.getChildCount());
+        assertTrue(mActivity.mChildren.contains(win1));
+        assertTrue(mActivity.mChildren.contains(startingWin));
+        assertTrue(mActivity.mChildren.contains(baseWin));
+        assertTrue(mActivity.mChildren.contains(win4));
 
         // The starting window should be on-top of all other windows.
-        assertEquals(startingWin, mToken.mChildren.peekLast());
+        assertEquals(startingWin, mActivity.mChildren.peekLast());
 
         // The base application window should be below all other windows.
-        assertEquals(baseWin, mToken.mChildren.peekFirst());
-        mToken.removeImmediately();
+        assertEquals(baseWin, mActivity.mChildren.peekFirst());
+        mActivity.removeImmediately();
     }
 
     @Test
     @Presubmit
     public void testFindMainWindow() {
-        assertNull(mToken.findMainWindow());
+        assertNull(mActivity.findMainWindow());
 
-        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mToken, "window1");
-        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, mToken, "window11");
-        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, mToken, "window12");
-        assertEquals(window1, mToken.findMainWindow());
+        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window1");
+        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, mActivity, "window11");
+        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, mActivity, "window12");
+        assertEquals(window1, mActivity.findMainWindow());
         window1.mAnimatingExit = true;
-        assertEquals(window1, mToken.findMainWindow());
-        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, mToken,
+        assertEquals(window1, mActivity.findMainWindow());
+        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, mActivity,
                 "window2");
-        assertEquals(window2, mToken.findMainWindow());
-        mToken.removeImmediately();
+        assertEquals(window2, mActivity.findMainWindow());
+        mActivity.removeImmediately();
     }
 
     @Test
     @Presubmit
     public void testGetTopFullscreenWindow() {
-        assertNull(mToken.getTopFullscreenWindow());
+        assertNull(mActivity.getTopFullscreenWindow());
 
-        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mToken, "window1");
-        final WindowState window11 = createWindow(null, TYPE_APPLICATION, mToken, "window11");
-        final WindowState window12 = createWindow(null, TYPE_APPLICATION, mToken, "window12");
-        assertEquals(window12, mToken.getTopFullscreenWindow());
+        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window1");
+        final WindowState window11 = createWindow(null, TYPE_APPLICATION, mActivity, "window11");
+        final WindowState window12 = createWindow(null, TYPE_APPLICATION, mActivity, "window12");
+        assertEquals(window12, mActivity.getTopFullscreenWindow());
         window12.mAttrs.width = 500;
-        assertEquals(window11, mToken.getTopFullscreenWindow());
+        assertEquals(window11, mActivity.getTopFullscreenWindow());
         window11.mAttrs.width = 500;
-        assertEquals(window1, mToken.getTopFullscreenWindow());
-        mToken.removeImmediately();
+        assertEquals(window1, mActivity.getTopFullscreenWindow());
+        mActivity.removeImmediately();
     }
 
     @Test
@@ -155,11 +155,11 @@
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("AppWindow");
-        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
-        mToken.addWindow(appWindow);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+        mActivity.addWindow(appWindow);
 
         // Set initial orientation and update.
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
         mDisplayContent.updateOrientation(
                 mDisplayContent.getRequestedOverrideConfiguration(),
                 null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
@@ -167,7 +167,7 @@
         appWindow.mResizeReported = false;
 
         // Update the orientation to perform 180 degree rotation and check that resize was reported.
-        mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
         mDisplayContent.updateOrientation(
                 mDisplayContent.getRequestedOverrideConfiguration(),
                 null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
@@ -187,8 +187,8 @@
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("RotationByPolicy");
-        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
-        mToken.addWindow(appWindow);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+        mActivity.addWindow(appWindow);
 
         // Set initial orientation and update.
         performRotation(displayRotation, Surface.ROTATION_90);
@@ -208,10 +208,10 @@
 
     @Test
     public void testSizeCompatBounds() {
-        final Rect fixedBounds = mToken.getRequestedOverrideConfiguration().windowConfiguration
+        final Rect fixedBounds = mActivity.getRequestedOverrideConfiguration().windowConfiguration
                 .getBounds();
         fixedBounds.set(0, 0, 1200, 1600);
-        mToken.getRequestedOverrideConfiguration().windowConfiguration.setAppBounds(fixedBounds);
+        mActivity.getRequestedOverrideConfiguration().windowConfiguration.setAppBounds(fixedBounds);
         final Configuration newParentConfig = mTask.getConfiguration();
 
         // Change the size of the container to two times smaller with insets.
@@ -219,50 +219,50 @@
         final Rect containerAppBounds = newParentConfig.windowConfiguration.getAppBounds();
         final Rect containerBounds = newParentConfig.windowConfiguration.getBounds();
         containerBounds.set(0, 0, 600, 800);
-        mToken.onConfigurationChanged(newParentConfig);
+        mActivity.onConfigurationChanged(newParentConfig);
 
-        assertTrue(mToken.hasSizeCompatBounds());
-        assertEquals(containerAppBounds, mToken.getBounds());
+        assertTrue(mActivity.hasSizeCompatBounds());
+        assertEquals(containerAppBounds, mActivity.getBounds());
         assertEquals((float) containerAppBounds.width() / fixedBounds.width(),
-                mToken.getSizeCompatScale(), 0.0001f /* delta */);
+                mActivity.getSizeCompatScale(), 0.0001f /* delta */);
 
         // Change the width of the container to two times bigger.
         containerAppBounds.set(0, 0, 2400, 1600);
         containerBounds.set(containerAppBounds);
-        mToken.onConfigurationChanged(newParentConfig);
+        mActivity.onConfigurationChanged(newParentConfig);
 
-        assertTrue(mToken.hasSizeCompatBounds());
+        assertTrue(mActivity.hasSizeCompatBounds());
         // Don't scale up, so the bounds keep the same as the fixed width.
-        assertEquals(fixedBounds.width(), mToken.getBounds().width());
+        assertEquals(fixedBounds.width(), mActivity.getBounds().width());
         // Assert the position is horizontal center.
         assertEquals((containerAppBounds.width() - fixedBounds.width()) / 2,
-                mToken.getBounds().left);
-        assertEquals(1f, mToken.getSizeCompatScale(), 0.0001f  /* delta */);
+                mActivity.getBounds().left);
+        assertEquals(1f, mActivity.getSizeCompatScale(), 0.0001f  /* delta */);
 
         // Change the width of the container to fit the fixed bounds.
         containerBounds.set(0, 0, 1200, 2000);
-        mToken.onConfigurationChanged(newParentConfig);
+        mActivity.onConfigurationChanged(newParentConfig);
         // Assert don't use fixed bounds because the region is enough.
-        assertFalse(mToken.hasSizeCompatBounds());
+        assertFalse(mActivity.hasSizeCompatBounds());
     }
 
     @Test
     @Presubmit
     public void testGetOrientation() {
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
-        mToken.setOccludesParent(false);
+        mActivity.setOccludesParent(false);
         // Can specify orientation if app doesn't occludes parent.
-        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mActivity.getOrientation());
 
-        mToken.setOccludesParent(true);
-        mToken.setHidden(true);
-        mToken.sendingToBottom = true;
+        mActivity.setOccludesParent(true);
+        mActivity.setHidden(true);
+        mActivity.sendingToBottom = true;
         // Can not specify orientation if app isn't visible even though it occludes parent.
-        assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_UNSET, mActivity.getOrientation());
         // Can specify orientation if the current orientation candidate is orientation behind.
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE,
-                mToken.getOrientation(SCREEN_ORIENTATION_BEHIND));
+                mActivity.getOrientation(SCREEN_ORIENTATION_BEHIND));
     }
 
     @Test
@@ -272,24 +272,24 @@
                 TYPE_BASE_APPLICATION);
         attrs.flags |= FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD;
         attrs.setTitle("AppWindow");
-        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mToken);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
 
         // Add window with show when locked flag
-        mToken.addWindow(appWindow);
-        assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
+        mActivity.addWindow(appWindow);
+        assertTrue(mActivity.containsShowWhenLockedWindow() && mActivity.containsDismissKeyguardWindow());
 
         // Start relaunching
-        mToken.startRelaunching();
-        assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
+        mActivity.startRelaunching();
+        assertTrue(mActivity.containsShowWhenLockedWindow() && mActivity.containsDismissKeyguardWindow());
 
         // Remove window and make sure that we still report back flag
-        mToken.removeChild(appWindow);
-        assertTrue(mToken.containsShowWhenLockedWindow() && mToken.containsDismissKeyguardWindow());
+        mActivity.removeChild(appWindow);
+        assertTrue(mActivity.containsShowWhenLockedWindow() && mActivity.containsDismissKeyguardWindow());
 
         // Finish relaunching and ensure flag is now not reported
-        mToken.finishRelaunching();
+        mActivity.finishRelaunching();
         assertFalse(
-                mToken.containsShowWhenLockedWindow() || mToken.containsDismissKeyguardWindow());
+                mActivity.containsShowWhenLockedWindow() || mActivity.containsDismissKeyguardWindow());
     }
 
     @Test
@@ -298,11 +298,11 @@
                 "closingWindow");
         closingWindow.mAnimatingExit = true;
         closingWindow.mRemoveOnExit = true;
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
 
         // We pretended that we were running an exit animation, but that should have been cleared up
-        // by changing visibility of AppWindowToken
+        // by changing visibility of ActivityRecord
         closingWindow.removeIfPossible();
         assertTrue(closingWindow.mRemoved);
     }
@@ -310,14 +310,14 @@
     @Test
     public void testSetOrientation() {
         // Assert orientation is unspecified to start.
-        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mActivity.getOrientation());
 
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
-        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mActivity.getOrientation());
 
-        mDisplayContent.removeAppToken(mToken.token);
+        mDisplayContent.removeAppToken(mActivity.token);
         // Assert orientation is unset to after container is removed.
-        assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_UNSET, mActivity.getOrientation());
 
         // Reset display frozen state
         mWm.mDisplayFrozen = false;
@@ -325,13 +325,13 @@
 
     @Test
     public void testReportOrientationChange() {
-        mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         mDisplayContent.getDisplayRotation().setFixedToUserRotation(
                 DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
 
         mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS);
-        mToken.reportDescendantOrientationChangeIfNeeded();
+        mActivity.reportDescendantOrientationChangeIfNeeded();
 
         verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class));
     }
@@ -339,14 +339,14 @@
     @Test
     @FlakyTest(bugId = 131176283)
     public void testCreateRemoveStartingWindow() {
-        mToken.addStartingWindow(mPackageName,
+        mActivity.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
-        assertHasStartingWindow(mToken);
-        mToken.removeStartingWindow();
+        assertHasStartingWindow(mActivity);
+        mActivity.removeStartingWindow();
         waitUntilHandlersIdle();
-        assertNoStartingWindow(mToken);
+        assertNoStartingWindow(mActivity);
     }
 
     @Test
@@ -354,7 +354,7 @@
     public void testAddRemoveRace() {
         // There was once a race condition between adding and removing starting windows
         for (int i = 0; i < 1000; i++) {
-            final AppWindowToken appToken = createIsolatedTestAppWindowToken();
+            final ActivityRecord appToken = createIsolatedTestActivityRecord();
 
             appToken.addStartingWindow(mPackageName,
                     android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
@@ -369,76 +369,76 @@
 
     @Test
     public void testTransferStartingWindow() {
-        final AppWindowToken token1 = createIsolatedTestAppWindowToken();
-        final AppWindowToken token2 = createIsolatedTestAppWindowToken();
-        token1.addStartingWindow(mPackageName,
+        final ActivityRecord activity1 = createIsolatedTestActivityRecord();
+        final ActivityRecord activity2 = createIsolatedTestActivityRecord();
+        activity1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
-        token2.addStartingWindow(mPackageName,
-                android.R.style.Theme, null, "Test", 0, 0, 0, 0, token1.appToken.asBinder(),
+        activity2.addStartingWindow(mPackageName,
+                android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1.appToken.asBinder(),
                 true, true, false, true, false, false);
         waitUntilHandlersIdle();
-        assertNoStartingWindow(token1);
-        assertHasStartingWindow(token2);
+        assertNoStartingWindow(activity1);
+        assertHasStartingWindow(activity2);
     }
 
     @Test
     public void testTransferStartingWindowWhileCreating() {
-        final AppWindowToken token1 = createIsolatedTestAppWindowToken();
-        final AppWindowToken token2 = createIsolatedTestAppWindowToken();
-        ((TestWindowManagerPolicy) token1.mWmService.mPolicy).setRunnableWhenAddingSplashScreen(
+        final ActivityRecord activity1 = createIsolatedTestActivityRecord();
+        final ActivityRecord activity2 = createIsolatedTestActivityRecord();
+        ((TestWindowManagerPolicy) activity1.mWmService.mPolicy).setRunnableWhenAddingSplashScreen(
                 () -> {
                     // Surprise, ...! Transfer window in the middle of the creation flow.
-                    token2.addStartingWindow(mPackageName,
+                    activity2.addStartingWindow(mPackageName,
                             android.R.style.Theme, null, "Test", 0, 0, 0, 0,
-                            token1.appToken.asBinder(), true, true, false,
+                            activity1.appToken.asBinder(), true, true, false,
                             true, false, false);
                 });
-        token1.addStartingWindow(mPackageName,
+        activity1.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
-        assertNoStartingWindow(token1);
-        assertHasStartingWindow(token2);
+        assertNoStartingWindow(activity1);
+        assertHasStartingWindow(activity2);
     }
 
-    private AppWindowToken createIsolatedTestAppWindowToken() {
+    private ActivityRecord createIsolatedTestActivityRecord() {
         final TaskStack taskStack = createTaskStackOnDisplay(mDisplayContent);
         final Task task = createTaskInStack(taskStack, 0 /* userId */);
-        return createTestAppWindowTokenForGivenTask(task);
+        return createTestActivityRecordForGivenTask(task);
     }
 
-    private AppWindowToken createTestAppWindowTokenForGivenTask(Task task) {
-        final ActivityRecord appToken =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task.addChild(appToken, 0);
+    private ActivityRecord createTestActivityRecordForGivenTask(Task task) {
+        final ActivityRecord activity =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task.addChild(activity, 0);
         waitUntilHandlersIdle();
-        return appToken;
+        return activity;
     }
 
     @Test
     public void testTryTransferStartingWindowFromHiddenAboveToken() {
         // Add two tasks on top of each other.
-        final AppWindowToken tokenTop = createIsolatedTestAppWindowToken();
-        final AppWindowToken tokenBottom =
-                createTestAppWindowTokenForGivenTask(tokenTop.getTask());
+        final ActivityRecord activityTop = createIsolatedTestActivityRecord();
+        final ActivityRecord activityBottom =
+                createTestActivityRecordForGivenTask(activityTop.getTask());
 
         // Add a starting window.
-        tokenTop.addStartingWindow(mPackageName,
+        activityTop.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                 false, false);
         waitUntilHandlersIdle();
 
         // Make the top one invisible, and try transferring the starting window from the top to the
         // bottom one.
-        tokenTop.setVisibility(false, false);
-        tokenBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
+        activityTop.setVisibility(false, false);
+        activityBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
         waitUntilHandlersIdle();
 
         // Assert that the bottom window now has the starting window.
-        assertNoStartingWindow(tokenTop);
-        assertHasStartingWindow(tokenBottom);
+        assertNoStartingWindow(activityTop);
+        assertHasStartingWindow(activityBottom);
     }
 
     @Test
@@ -450,40 +450,40 @@
 
         // Check that anim bounds for freeform window match task bounds
         mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
-        assertEquals(taskBounds, mToken.getAnimationBounds(STACK_CLIP_NONE));
+        assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_NONE));
 
         // STACK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by
         // bounds animation layer.
         mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        assertEquals(taskBounds, mToken.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
+        assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
 
         // STACK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later.
         mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        assertEquals(stackBounds, mToken.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
+        assertEquals(stackBounds, mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
     }
 
     @Test
     public void testHasStartingWindow() {
         final WindowManager.LayoutParams attrs =
                 new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
-        final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mToken);
-        mToken.startingDisplayed = true;
-        mToken.addWindow(startingWindow);
-        assertTrue("Starting window should be present", mToken.hasStartingWindow());
-        mToken.startingDisplayed = false;
-        assertTrue("Starting window should be present", mToken.hasStartingWindow());
+        final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mActivity);
+        mActivity.startingDisplayed = true;
+        mActivity.addWindow(startingWindow);
+        assertTrue("Starting window should be present", mActivity.hasStartingWindow());
+        mActivity.startingDisplayed = false;
+        assertTrue("Starting window should be present", mActivity.hasStartingWindow());
 
-        mToken.removeChild(startingWindow);
-        assertFalse("Starting window should not be present", mToken.hasStartingWindow());
+        mActivity.removeChild(startingWindow);
+        assertFalse("Starting window should not be present", mActivity.hasStartingWindow());
     }
 
-    private void assertHasStartingWindow(AppWindowToken atoken) {
+    private void assertHasStartingWindow(ActivityRecord atoken) {
         assertNotNull(atoken.startingSurface);
         assertNotNull(atoken.mStartingData);
         assertNotNull(atoken.startingWindow);
     }
 
-    private void assertNoStartingWindow(AppWindowToken atoken) {
+    private void assertNoStartingWindow(ActivityRecord atoken) {
         assertNull(atoken.startingSurface);
         assertNull(atoken.startingWindow);
         assertNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index f12c349..01489c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -113,13 +113,13 @@
     public void testForAllWindows() {
         final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
                 mDisplayContent, "exiting app");
-        final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+        final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
         // Wait until everything in animation handler get executed to prevent the exiting window
         // from being removed during WindowSurfacePlacer Traversal.
         waitUntilHandlersIdle();
 
-        exitingAppToken.mIsExiting = true;
-        exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
+        exitingApp.mIsExiting = true;
+        exitingApp.getTask().mStack.mExitingActivities.add(exitingApp);
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -241,10 +241,10 @@
         assertEquals(dc, stack.getDisplayContent());
 
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final ActivityRecord token = WindowTestUtils.createTestAppWindowToken(dc);
-        task.addChild(token, 0);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
+        task.addChild(activity, 0);
         assertEquals(dc, task.getDisplayContent());
-        assertEquals(dc, token.getDisplayContent());
+        assertEquals(dc, activity.getDisplayContent());
 
         // Move stack to first display.
         mDisplayContent.moveStackToDisplay(stack, true /* onTop */);
@@ -252,7 +252,7 @@
         assertEquals(mDisplayContent, stack.getParent().getParent());
         assertEquals(mDisplayContent, stack.getDisplayContent());
         assertEquals(mDisplayContent, task.getDisplayContent());
-        assertEquals(mDisplayContent, token.getDisplayContent());
+        assertEquals(mDisplayContent, activity.getDisplayContent());
     }
 
     /**
@@ -313,17 +313,17 @@
         // Add stack with activity.
         final TaskStack stack0 = createTaskStackOnDisplay(dc0);
         final Task task0 = createTaskInStack(stack0, 0 /* userId */);
-        final ActivityRecord token =
-                WindowTestUtils.createTestAppWindowToken(dc0);
-        task0.addChild(token, 0);
+        final ActivityRecord activity =
+                WindowTestUtils.createTestActivityRecord(dc0);
+        task0.addChild(activity, 0);
         dc0.configureDisplayPolicy();
         assertNotNull(dc0.mTapDetector);
 
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
-        final ActivityRecord token1 =
-                WindowTestUtils.createTestAppWindowToken(dc0);
-        task1.addChild(token1, 0);
+        final ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(dc0);
+        task1.addChild(activity1, 0);
         dc1.configureDisplayPolicy();
         assertNotNull(dc1.mTapDetector);
 
@@ -362,7 +362,7 @@
         // Create a focusable window and check that focus is calculated correctly
         final WindowState window1 =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
-        window1.mAppToken.mTargetSdk = targetSdk;
+        window1.mActivityRecord.mTargetSdk = targetSdk;
         updateFocusedWindow();
         assertTrue(window1.isFocused());
         assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
@@ -375,7 +375,7 @@
 
         // Add a window to the second display, and it should be focused
         final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, dc, "window2");
-        window2.mAppToken.mTargetSdk = targetSdk;
+        window2.mActivityRecord.mTargetSdk = targetSdk;
         updateFocusedWindow();
         assertTrue(window2.isFocused());
         assertEquals(perDisplayFocusEnabled && targetSdk >= Q, window1.isFocused());
@@ -389,8 +389,8 @@
         assertEquals(window1, mWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus);
 
         // Make sure top focused display not changed if there is a focused app.
-        window1.mAppToken.hiddenRequested = true;
-        window1.getDisplayContent().setFocusedApp(window1.mAppToken);
+        window1.mActivityRecord.hiddenRequested = true;
+        window1.getDisplayContent().setFocusedApp(window1.mActivityRecord);
         updateFocusedWindow();
         assertTrue(!window1.isFocused());
         assertEquals(window1.getDisplayId(),
@@ -569,7 +569,7 @@
         // Create a window that requests landscape orientation. It will define device orientation
         // by default.
         final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
-        window.mAppToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR, dc, "keyguard");
         keyguard.mHasSurface = true;
@@ -747,7 +747,7 @@
                      new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
             final DisplayContent dc = createNewDisplay();
             dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
-            assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
+            assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
                     dc.computeImeParent());
         }
     }
@@ -766,8 +766,8 @@
 
     @Test
     public void testComputeImeParent_app_notMatchParentBounds() {
-        spyOn(mAppWindow.mAppToken);
-        doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
+        spyOn(mAppWindow.mActivityRecord);
+        doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
         mDisplayContent.mInputMethodTarget = mAppWindow;
         // The surface parent of IME should be the display instead of app window.
         assertEquals(mDisplayContent.getWindowingLayer(), mDisplayContent.computeImeParent());
@@ -881,7 +881,7 @@
         win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility =
                 SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION
                         | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-        win.mAppToken.mTargetSdk = P;
+        win.mActivityRecord.mTargetSdk = P;
 
         dc.setLayoutNeeded();
         dc.performLayout(true /* initial */, false /* updateImeWindows */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 480c468..bb4d35f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -638,7 +638,7 @@
         mBuilder.build();
 
         final WindowState win = mock(WindowState.class);
-        win.mAppToken = mock(AppWindowToken.class);
+        win.mActivityRecord = mock(ActivityRecord.class);
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
         attrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
 
@@ -648,13 +648,13 @@
         mMockDisplayContent.mCurrentFocus = win;
         mTarget.mUpsideDownRotation = Surface.ROTATION_180;
 
-        doReturn(true).when(win.mAppToken).matchParentBounds();
+        doReturn(true).when(win.mActivityRecord).matchParentBounds();
         // The focused fullscreen opaque window without override bounds should be able to be
         // rotated seamlessly.
         assertTrue(mTarget.shouldRotateSeamlessly(
                 Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */));
 
-        doReturn(false).when(win.mAppToken).matchParentBounds();
+        doReturn(false).when(win.mActivityRecord).matchParentBounds();
         // No seamless rotation if the window may be positioned with offset after rotation.
         assertFalse(mTarget.shouldRotateSeamlessly(
                 Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 452e06f..bfb4607 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -96,15 +96,15 @@
      * Creates a window state which can be used as a drop target.
      */
     private WindowState createDropTargetWindow(String name, int ownerId) {
-        final ActivityRecord token = WindowTestUtils.createTestAppWindowToken(
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(
                 mDisplayContent);
         final TaskStack stack = createTaskStackOnDisplay(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
         final Task task = createTaskInStack(stack, ownerId);
-        task.addChild(token, 0);
+        task.addChild(activity, 0);
 
         final WindowState window = createWindow(
-                null, TYPE_BASE_APPLICATION, token, name, ownerId, false);
+                null, TYPE_BASE_APPLICATION, activity, name, ownerId, false);
         window.mInputChannel = new InputChannel();
         window.mHasSurface = true;
         return window;
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index f3a8e1a..8c2ae5a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -19,6 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.InsetsState.TYPE_TOP_BAR;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -32,7 +33,9 @@
 import static org.junit.Assert.assertNull;
 
 import android.platform.test.annotations.Presubmit;
+import android.util.IntArray;
 import android.view.InsetsSourceControl;
+import android.view.InsetsState;
 import android.view.test.InsetsModeSession;
 
 import androidx.test.filters.FlakyTest;
@@ -151,6 +154,91 @@
         assertEquals(1, controls.length);
     }
 
+    @Test
+    public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
+        addWindow(TYPE_STATUS_BAR, "topBar")
+                .getControllableInsetProvider().getSource().setVisible(false);
+        addWindow(TYPE_NAVIGATION_BAR, "navBar")
+                .getControllableInsetProvider().getSource().setVisible(false);
+        final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
+        final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+        policy.updateBarControlTarget(app);
+        policy.showTransient(
+                IntArray.wrap(new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+        final InsetsSourceControl[] controls =
+                mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+        // The app must get both fake controls.
+        assertEquals(2, controls.length);
+        for (int i = controls.length - 1; i >= 0; i--) {
+            assertNull(controls[i].getLeash());
+        }
+    }
+
+    @Test
+    public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() {
+        addWindow(TYPE_STATUS_BAR, "topBar")
+                .getControllableInsetProvider().getSource().setVisible(false);
+        addWindow(TYPE_NAVIGATION_BAR, "navBar")
+                .getControllableInsetProvider().getSource().setVisible(true);
+        final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
+        final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+        policy.updateBarControlTarget(app);
+        policy.showTransient(
+                IntArray.wrap(new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+        final InsetsSourceControl[] controls =
+                mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+        // The app must get the fake control of the top bar, and must get the real control of the
+        // navigation bar.
+        assertEquals(2, controls.length);
+        for (int i = controls.length - 1; i >= 0; i--) {
+            final InsetsSourceControl control = controls[i];
+            if (control.getType() == TYPE_TOP_BAR) {
+                assertNull(controls[i].getLeash());
+            } else {
+                assertNotNull(controls[i].getLeash());
+            }
+        }
+    }
+
+    @Test
+    public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() {
+        addWindow(TYPE_STATUS_BAR, "topBar")
+                .getControllableInsetProvider().getSource().setVisible(false);
+        addWindow(TYPE_NAVIGATION_BAR, "navBar")
+                .getControllableInsetProvider().getSource().setVisible(false);
+        final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
+        final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
+        policy.updateBarControlTarget(app);
+        policy.showTransient(
+                IntArray.wrap(new int[]{TYPE_TOP_BAR, InsetsState.TYPE_NAVIGATION_BAR}));
+        InsetsSourceControl[] controls =
+                mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+        // The app must get both fake controls.
+        assertEquals(2, controls.length);
+        for (int i = controls.length - 1; i >= 0; i--) {
+            assertNull(controls[i].getLeash());
+        }
+
+        final InsetsState state = policy.getInsetsForDispatch(app);
+        state.setSourceVisible(TYPE_TOP_BAR, true);
+        state.setSourceVisible(InsetsState.TYPE_NAVIGATION_BAR, true);
+        policy.onInsetsModified(app, state);
+
+        controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(app);
+
+        // The app must get both real controls.
+        assertEquals(2, controls.length);
+        for (int i = controls.length - 1; i >= 0; i--) {
+            assertNotNull(controls[i].getLeash());
+        }
+    }
+
     private WindowState addWindow(int type, String name) {
         final WindowState win = createWindow(null, type, name);
         mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 81ea32b..011161b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -66,7 +66,7 @@
         final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
-        topBar.setInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
+        topBar.setControllableInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
         assertNotNull(getController().getInsetsForDispatch(app).getSource(TYPE_TOP_BAR));
     }
 
@@ -75,7 +75,7 @@
         final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
         mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
                 .setWindow(topBar, null);
-        topBar.setInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
+        topBar.setControllableInsetProvider(getController().getSourceProvider(TYPE_TOP_BAR));
         final InsetsState state = getController().getInsetsForDispatch(topBar);
         for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
             final InsetsSource source = state.sourceAt(i);
@@ -101,7 +101,7 @@
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
         getController().getSourceProvider(TYPE_NAVIGATION_BAR).setWindow(navBar, null);
-        getController().onBarControlTargetChanged(app, app);
+        getController().onBarControlTargetChanged(app, null, app, null);
         InsetsSourceControl[] controls = getController().getControlsForDispatch(app);
         assertEquals(2, controls.length);
     }
@@ -111,9 +111,9 @@
         final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
-        getController().onBarControlTargetChanged(app, null);
+        getController().onBarControlTargetChanged(app, null, null, null);
         assertNotNull(getController().getControlsForDispatch(app));
-        getController().onBarControlTargetChanged(null, null);
+        getController().onBarControlTargetChanged(null, null, null, null);
         assertNull(getController().getControlsForDispatch(app));
     }
 
@@ -123,7 +123,7 @@
         final WindowState topBar = createWindow(null, TYPE_APPLICATION, "topBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         getController().getSourceProvider(TYPE_TOP_BAR).setWindow(topBar, null);
-        getController().onBarControlTargetChanged(app, null);
+        getController().onBarControlTargetChanged(app, null, null, null);
         assertNotNull(getController().getControlsForDispatch(app));
         topBar.cancelAnimation();
         assertNull(getController().getControlsForDispatch(app));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
index acbbc46..d1510cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
@@ -44,14 +44,32 @@
     @Test
     public void testProtoLogToolIntegration() {
         ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class);
-        ProtoLogImpl.setSingleInstance(mockedProtoLog);
-        ProtoLogGroup.testProtoLog();
-        verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.ERROR), eq(
-                ProtoLogGroup.TEST_GROUP),
+        runWith(mockedProtoLog, () -> {
+            ProtoLogGroup.testProtoLog();
+        });
+        verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.ERROR), eq(ProtoLogGroup.TEST_GROUP),
                 anyInt(), eq(0b0010101001010111),
                 eq(ProtoLogGroup.TEST_GROUP.isLogToLogcat()
                         ? "Test completed successfully: %b %d %o %x %e %g %f %% %s"
                         : null),
                 eq(new Object[]{true, 1L, 2L, 3L, 0.4, 0.5, 0.6, "ok"}));
     }
+
+    /**
+     * Starts protolog for the duration of {@code runnable}, with a ProtoLogImpl instance installed.
+     */
+    private void runWith(ProtoLogImpl mockInstance, Runnable runnable) {
+        ProtoLogImpl original = ProtoLogImpl.getSingleInstance();
+        original.startProtoLog(null);
+        try {
+            ProtoLogImpl.setSingleInstance(mockInstance);
+            try {
+                runnable.run();
+            } finally {
+                ProtoLogImpl.setSingleInstance(original);
+            }
+        } finally {
+            original.stopProtoLog(null, false);
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index f353846..7026004 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -99,14 +99,14 @@
 
     @Test
     public void testRemovedBeforeStarted_expectCanceled() throws Exception {
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        AnimationAdapter adapter = mController.addAnimation(appWindow.getTask(),
+        AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
                 false /* isRecentTaskInvisible */);
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
 
         // Remove the app window so that the animation target can not be created
-        appWindow.removeImmediately();
+        activity.removeImmediately();
         mController.startAnimation();
 
         // Verify that the finish callback to reparent the leash is called
@@ -118,14 +118,14 @@
 
     @Test
     public void testCancelAfterRemove_expectIgnored() {
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        AnimationAdapter adapter = mController.addAnimation(appWindow.getTask(),
+        AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
                 false /* isRecentTaskInvisible */);
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
 
         // Remove the app window so that the animation target can not be created
-        appWindow.removeImmediately();
+        activity.removeImmediately();
         mController.startAnimation();
         mController.cleanupAnimation(REORDER_KEEP_IN_PLACE);
         try {
@@ -140,24 +140,24 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final AppWindowToken hiddenAppWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord hiddenActivity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        hiddenAppWindow.setHidden(true);
+        hiddenActivity.setHidden(true);
         mDisplayContent.getConfiguration().windowConfiguration.setRotation(
                 mDisplayContent.getRotation());
-        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray());
+        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
 
         // Ensure that we are animating the target activity as well
-        assertTrue(mController.isAnimatingTask(homeAppWindow.getTask()));
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
-        assertFalse(mController.isAnimatingTask(hiddenAppWindow.getTask()));
+        assertTrue(mController.isAnimatingTask(homeActivity.getTask()));
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
+        assertFalse(mController.isAnimatingTask(hiddenActivity.getTask()));
     }
 
     @Test
@@ -165,12 +165,12 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeAppWindow =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord appWindow = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
         appWindow.addWindow(win1);
@@ -181,7 +181,7 @@
 
         mDisplayContent.getConfiguration().windowConfiguration.setRotation(
                 mDisplayContent.getRotation());
-        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray());
+        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeAppWindow);
         mController.startAnimation();
 
         // Ensure that we are animating the app and wallpaper target
@@ -194,15 +194,15 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
         final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
                 mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
         spyOn(mDisplayContent.mWallpaperController);
@@ -210,12 +210,12 @@
 
         mDisplayContent.getConfiguration().windowConfiguration.setRotation(
                 mDisplayContent.getRotation());
-        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray());
+        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
         mController.startAnimation();
 
         // Cancel the animation and ensure the controller is still running
         wallpaperWindowToken.cancelAnimation();
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
         assertFalse(mController.isAnimatingWallpaper(wallpaperWindowToken));
         verify(mMockRunner, never()).onAnimationCanceled(null /* taskSnapshot */);
     }
@@ -225,24 +225,24 @@
         mWm.setRecentsAnimationController(mController);
         final ActivityStack homeStack = mDisplayContent.mActivityDisplay.getOrCreateStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
-        final AppWindowToken homeAppWindow =
+        final ActivityRecord homeActivity =
                 new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
                         .setStack(homeStack)
                         .setCreateTask(true)
                         .build();
-        final WindowState hwin1 = createWindow(null, TYPE_BASE_APPLICATION, homeAppWindow, "hwin1");
-        homeAppWindow.addWindow(hwin1);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final WindowState hwin1 = createWindow(null, TYPE_BASE_APPLICATION, homeActivity, "hwin1");
+        homeActivity.addWindow(hwin1);
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
         final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
                 mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
         spyOn(mDisplayContent.mWallpaperController);
         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
 
         // Start and finish the animation
-        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray());
+        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
         mController.startAnimation();
         // Reset at this point since we may remove adapters that couldn't be created
         reset(mController);
@@ -256,15 +256,15 @@
     @Test
     public void testDeferCancelAnimation() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
-        assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow);
-        assertEquals(appWindow.findMainWindow(), win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
+        assertEquals(activity.getTask().getTopVisibleActivity(), activity);
+        assertEquals(activity.findMainWindow(), win1);
 
-        mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
 
         mController.setDeferredCancel(true /* deferred */, false /* screenshot */);
         mController.cancelAnimationWithScreenshot(false /* screenshot */);
@@ -279,15 +279,15 @@
     @Test
     public void testDeferCancelAnimationWithScreenShot() throws Exception {
         mWm.setRecentsAnimationController(mController);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
-        assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow);
-        assertEquals(appWindow.findMainWindow(), win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
+        assertEquals(activity.getTask().getTopVisibleActivity(), activity);
+        assertEquals(activity.findMainWindow(), win1);
 
-        mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
 
         spyOn(mWm.mTaskSnapshotController);
         doNothing().when(mWm.mTaskSnapshotController).notifyAppVisibilityChanged(any(),
@@ -311,20 +311,20 @@
     @Test
     public void testShouldAnimateWhenNoCancelWithDeferredScreenshot() {
         mWm.setRecentsAnimationController(mController);
-        final AppWindowToken appWindow = createAppWindowToken(mDisplayContent,
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
-        appWindow.addWindow(win1);
-        assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow);
-        assertEquals(appWindow.findMainWindow(), win1);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
+        activity.addWindow(win1);
+        assertEquals(activity.getTask().getTopVisibleActivity(), activity);
+        assertEquals(activity.findMainWindow(), win1);
 
-        mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */);
-        assertTrue(mController.isAnimatingTask(appWindow.getTask()));
+        mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
+        assertTrue(mController.isAnimatingTask(activity.getTask()));
 
-        // Assume appWindow transition should animate when no
+        // Assume activity transition should animate when no
         // IRecentsAnimationController#setCancelWithDeferredScreenshot called.
         assertFalse(mController.shouldDeferCancelWithScreenshot());
-        assertTrue(appWindow.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
+        assertTrue(activity.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
     }
 
     private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index ebedde7..839ddb2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -78,7 +78,7 @@
         mRecentsAnimationController = mock(RecentsAnimationController.class);
         mService.mWindowManager.setRecentsAnimationController(mRecentsAnimationController);
         doNothing().when(mService.mWindowManager).initializeRecentsAnimation(
-                anyInt(), any(), any(), anyInt(), any());
+                anyInt(), any(), any(), anyInt(), any(), any());
         doReturn(true).when(mService.mWindowManager).canStartRecentsAnimation();
 
         final RecentTasks recentTasks = mService.getRecentTasks();
@@ -385,7 +385,8 @@
                 return null;
             }).when(mService.mWindowManager).initializeRecentsAnimation(
                     anyInt() /* targetActivityType */, any() /* recentsAnimationRunner */,
-                    any() /* callbacks */, anyInt() /* displayId */, any() /* recentTaskIds */);
+                    any() /* callbacks */, anyInt() /* displayId */, any() /* recentTaskIds */,
+                    any() /* targetActivity */);
         }
 
         Intent recentsIntent = new Intent();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index efc2fd6..a23425f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -106,7 +106,7 @@
                 "overrideWindow");
         overrideWindow.mAttrs.packageName = "com.android.test";
         overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID;
-        overrideWindow.mAppToken.mSurfaceAnimator.startAnimation(
+        overrideWindow.mActivityRecord.mSurfaceAnimator.startAnimation(
                 overrideWindow.getPendingTransaction(), mock(AnimationAdapter.class),
                 false /* hidden */);
         mPolicy.addNonHighRefreshRatePackage("com.android.test");
@@ -122,7 +122,7 @@
         mPolicy.addNonHighRefreshRatePackage("com.android.test");
         assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow));
 
-        cameraUsingWindow.mAppToken.mSurfaceAnimator.startAnimation(
+        cameraUsingWindow.mActivityRecord.mSurfaceAnimator.startAnimation(
                 cameraUsingWindow.getPendingTransaction(), mock(AnimationAdapter.class),
                 false /* hidden */);
         assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 3b9c3bb..e353903 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -91,9 +91,9 @@
     @Test
     public void testRun() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mOpeningApps.add(win.mAppToken);
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
         try {
-            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                     new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
@@ -110,8 +110,8 @@
             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
             assertEquals(new Point(50, 100), app.position);
             assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
-            assertEquals(win.mAppToken.getPrefixOrderIndex(), app.prefixOrderIndex);
-            assertEquals(win.mAppToken.getTask().mTaskId, app.taskId);
+            assertEquals(win.mActivityRecord.getPrefixOrderIndex(), app.prefixOrderIndex);
+            assertEquals(win.mActivityRecord.getTask().mTaskId, app.taskId);
             assertEquals(mMockLeash, app.leash);
             assertEquals(win.mWinAnimator.mLastClipRect, app.clipRect);
             assertEquals(false, app.isTranslucent);
@@ -129,7 +129,7 @@
     @Test
     public void testCancel() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
         mController.goodToGo();
@@ -142,7 +142,7 @@
     @FlakyTest(bugId = 133372977)
     public void testTimeout() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
         mController.goodToGo();
@@ -161,7 +161,7 @@
             final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
                     "testWin");
             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
-                    win.mAppToken, new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
+                    win.mActivityRecord, new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
 
@@ -189,7 +189,7 @@
     @Test
     public void testNotReallyStarted() {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mController.createRemoteAnimationRecord(win.mAppToken,
+        mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null);
         mController.goodToGo();
         verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
@@ -199,9 +199,9 @@
     public void testOneNotStarted() throws Exception {
         final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
         final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
-        mController.createRemoteAnimationRecord(win1.mAppToken,
+        mController.createRemoteAnimationRecord(win1.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null);
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win2.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win2.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
         mController.goodToGo();
@@ -221,10 +221,10 @@
     @Test
     public void testRemovedBeforeStarted() {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
         adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
-        win.mAppToken.removeImmediately();
+        win.mActivityRecord.removeImmediately();
         mController.goodToGo();
         verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
         verify(mFinishedCallback).onAnimationFinished(eq(adapter));
@@ -233,10 +233,10 @@
     @Test
     public void testChange() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mChangingApps.add(win.mAppToken);
+        mDisplayContent.mChangingApps.add(win.mActivityRecord);
         try {
             final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
-                    win.mAppToken, new Point(50, 100), new Rect(50, 100, 150, 150),
+                    win.mActivityRecord, new Point(50, 100), new Rect(50, 100, 150, 150),
                     new Rect(0, 0, 200, 200));
             assertNotNull(record.mThumbnailAdapter);
             ((AnimationAdapter) record.mAdapter)
@@ -284,9 +284,9 @@
         spyOn(mDisplayContent.mWallpaperController);
         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mOpeningApps.add(win.mAppToken);
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
         try {
-            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                     new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
@@ -312,9 +312,9 @@
         spyOn(mDisplayContent.mWallpaperController);
         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
-        mDisplayContent.mOpeningApps.add(win.mAppToken);
+        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
         try {
-            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mAppToken,
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                     new Point(50, 100), new Rect(50, 100, 150, 150), null).mAdapter;
             adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
             mController.goodToGo();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 2b1c4ff..979aab6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -237,7 +237,7 @@
         mDeferFinishAnimatable.mFinishedCallbackCalled = false;
 
         // Simulate the first deferred callback is executed from
-        // {@link AnimatingAppWindowTokenRegistry#endDeferringFinished}.
+        // {@link AnimatingActivityRegistry#endDeferringFinished}.
         firstDeferFinishCallback.run();
         // The second animation should not be finished.
         assertFalse(mDeferFinishAnimatable.mFinishedCallbackCalled);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index ef9821b..fa1f435 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -415,8 +415,8 @@
             final AppOpsService aos = mock(AppOpsService.class);
             doReturn(aos).when(this).getAppOpsService();
             // Make sure permission checks aren't overridden.
-            doReturn(AppOpsManager.MODE_DEFAULT)
-                    .when(aos).noteOperation(anyInt(), anyInt(), anyString());
+            doReturn(AppOpsManager.MODE_DEFAULT).when(aos).noteOperation(anyInt(), anyInt(),
+                    anyString(), nullable(String.class));
 
             // UserManagerService
             final UserManagerService ums = mock(UserManagerService.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 3bedabc..bebb3ba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -54,7 +54,7 @@
         mCache.putSnapshot(window.getTask(), createSnapshot());
         assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
-        mCache.onAppRemoved(window.mAppToken);
+        mCache.onAppRemoved(window.mActivityRecord);
         assertNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
     }
@@ -65,7 +65,7 @@
         mCache.putSnapshot(window.getTask(), createSnapshot());
         assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
-        mCache.onAppDied(window.mAppToken);
+        mCache.onAppDied(window.mActivityRecord);
         assertNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
                 false /* restoreFromDisk */, false /* reducedResolution */));
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 113f3c8..3b11003 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -48,14 +48,14 @@
     public void testGetClosingApps_closing() {
         final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
                 "closingWindow");
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
-        closingApps.add(closingWindow.mAppToken);
+        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
+        closingApps.add(closingWindow.mActivityRecord);
         final ArraySet<Task> closingTasks = new ArraySet<>();
         mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
         assertEquals(1, closingTasks.size());
-        assertEquals(closingWindow.mAppToken.getTask(), closingTasks.valueAt(0));
+        assertEquals(closingWindow.mActivityRecord.getTask(), closingTasks.valueAt(0));
     }
 
     @Test
@@ -64,12 +64,12 @@
                 "closingWindow");
         final WindowState openingWindow = createAppWindow(closingWindow.getTask(),
                 FIRST_APPLICATION_WINDOW, "openingWindow");
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        openingWindow.mAppToken.commitVisibility(null, true /* visible */, TRANSIT_UNSET,
+        openingWindow.mActivityRecord.commitVisibility(null, true /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
-        closingApps.add(closingWindow.mAppToken);
+        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
+        closingApps.add(closingWindow.mActivityRecord);
         final ArraySet<Task> closingTasks = new ArraySet<>();
         mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
         assertEquals(0, closingTasks.size());
@@ -79,13 +79,13 @@
     public void testGetClosingApps_skipClosingAppsSnapshotTasks() {
         final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
                 "closingWindow");
-        closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
+        closingWindow.mActivityRecord.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
                 true /* performLayout */, false /* isVoiceInteraction */);
-        final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
-        closingApps.add(closingWindow.mAppToken);
+        final ArraySet<ActivityRecord> closingApps = new ArraySet<>();
+        closingApps.add(closingWindow.mActivityRecord);
         final ArraySet<Task> closingTasks = new ArraySet<>();
         mWm.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(
-                Sets.newArraySet(closingWindow.mAppToken.getTask()));
+                Sets.newArraySet(closingWindow.mActivityRecord.getTask()));
         mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
         assertEquals(0, closingTasks.size());
     }
@@ -94,7 +94,7 @@
     public void testGetSnapshotMode() {
         final WindowState disabledWindow = createWindow(null,
                 FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow");
-        disabledWindow.mAppToken.setDisablePreviewScreenshots(true);
+        disabledWindow.mActivityRecord.setDisablePreviewScreenshots(true);
         assertEquals(SNAPSHOT_MODE_APP_THEME,
                 mWm.mTaskSnapshotController.getSnapshotMode(disabledWindow.getTask()));
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index eef680b..a66c79c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -55,7 +55,7 @@
         final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
         assertFalse(mPinnedStack.isVisible());
         final ActivityRecord pinnedApp =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
         pinnedTask.addChild(pinnedApp, 0 /* addPos */);
         assertTrue(mPinnedStack.isVisible());
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index d045073..2fc03c7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -21,12 +21,15 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
@@ -68,19 +71,19 @@
     public void testClosingAppDifferentStackOrientation() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        ActivityRecord appWindowToken1 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task1.addChild(appWindowToken1, 0);
-        appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task1.addChild(activity1, 0);
+        activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        ActivityRecord appWindowToken2 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task2.addChild(appWindowToken2, 0);
-        appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
+        ActivityRecord activity2=
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task2.addChild(activity2, 0);
+        activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
-        mDisplayContent.mClosingApps.add(appWindowToken2);
+        mDisplayContent.mClosingApps.add(activity2);
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, stack.getOrientation());
     }
 
@@ -88,16 +91,16 @@
     public void testMoveTaskToBackDifferentStackOrientation() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        ActivityRecord appWindowToken1 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task1.addChild(appWindowToken1, 0);
-        appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        ActivityRecord activity1 =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task1.addChild(activity1, 0);
+        activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        ActivityRecord appWindowToken2 =
-                WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        task2.addChild(appWindowToken2, 0);
-        appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
+        ActivityRecord activity2 =
+                WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        task2.addChild(activity2, 0);
+        activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
         assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
         task2.setSendingToBottom(true);
@@ -119,7 +122,7 @@
     @Test
     public void testRemoveContainer() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack);
+        final Task task = createTaskInStack(stack, 0 /* userId */);
 
         assertNotNull(stack);
         assertNotNull(task);
@@ -135,10 +138,10 @@
     @Test
     public void testRemoveContainer_deferRemoval() {
         final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack);
+        final Task task = createTaskInStack(stack, 0 /* userId */);
 
         // Stack removal is deferred if one of its child is animating.
-        task.setLocalIsAnimating(true);
+        doReturn(true).when(task).isSelfAnimating();
 
         stack.removeIfPossible();
         // For the case of deferred removal the task controller will still be connected to the its
@@ -157,8 +160,7 @@
     public void testReparent() {
         // Create first stack on primary display.
         final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task1 = WindowTestUtils.createTestTask(stack1);
-        task1.mOnDisplayChangedCalled = false;
+        final Task task1 = createTaskInStack(stack1, 0 /* userId */);
 
         // Create second display and put second stack on it.
         final DisplayContent dc = createNewDisplay();
@@ -170,7 +172,7 @@
         final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
         final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2);
         assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
-        assertTrue(task1.mOnDisplayChangedCalled);
+        verify(task1, times(1)).onDisplayChanged(any());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index f117ff0..4dfa266 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -16,11 +16,16 @@
 
 package com.android.server.wm;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -45,45 +50,45 @@
     @Test
     public void testRemoveContainer() {
         final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
-        final AppWindowToken appToken =
-                WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
+        final Task task = createTaskInStack(stackController1, 0 /* userId */);
+        final ActivityRecord activity =
+                WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
 
         task.removeIfPossible();
         // Assert that the container was removed.
         assertNull(task.getParent());
         assertEquals(0, task.getChildCount());
-        assertNull(appToken.getParent());
+        assertNull(activity.getParent());
     }
 
     @Test
     public void testRemoveContainer_deferRemoval() {
         final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
-        final AppWindowToken appToken =
-                WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
+        final Task task = createTaskInStack(stackController1, 0 /* userId */);
+        final ActivityRecord activity =
+                WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
 
-        task.mShouldDeferRemoval = true;
+        doReturn(true).when(task).shouldDeferRemoval();
 
         task.removeIfPossible();
         // For the case of deferred removal the task will still be connected to the its app token
         // until the task window container is removed.
         assertNotNull(task.getParent());
         assertNotEquals(0, task.getChildCount());
-        assertNotNull(appToken.getParent());
+        assertNotNull(activity.getParent());
 
         task.removeImmediately();
         assertNull(task.getParent());
         assertEquals(0, task.getChildCount());
-        assertNull(appToken.getParent());
+        assertNull(activity.getParent());
     }
 
     @Test
     public void testReparent() {
         final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
+        final Task task = createTaskInStack(stackController1, 0 /* userId */);
         final TaskStack stackController2 = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stackController2);
+        final Task task2 = createTaskInStack(stackController2, 0 /* userId */);
 
         boolean gotException = false;
         try {
@@ -104,34 +109,33 @@
 
         task.reparent(stackController2, 0, false/* moveParents */);
         assertEquals(stackController2, task.getParent());
-        assertEquals(0, task.positionInParent());
-        assertEquals(1, task2.positionInParent());
+        assertEquals(0, task.getParent().mChildren.indexOf(task));
+        assertEquals(1, task2.getParent().mChildren.indexOf(task2));
     }
 
     @Test
     public void testReparent_BetweenDisplays() {
         // Create first stack on primary display.
         final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1);
-        task.mOnDisplayChangedCalled = false;
+        final Task task = createTaskInStack(stack1, 0 /* userId */);
         assertEquals(mDisplayContent, stack1.getDisplayContent());
 
         // Create second display and put second stack on it.
         final DisplayContent dc = createNewDisplay();
         final TaskStack stack2 = createTaskStackOnDisplay(dc);
-        final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stack2);
+        final Task task2 = createTaskInStack(stack2, 0 /* userId */);
         // Reparent and check state
         task.reparent(stack2, 0, false /* moveParents */);
         assertEquals(stack2, task.getParent());
-        assertEquals(0, task.positionInParent());
-        assertEquals(1, task2.positionInParent());
-        assertTrue(task.mOnDisplayChangedCalled);
+        assertEquals(0, task.getParent().mChildren.indexOf(task));
+        assertEquals(1, task2.getParent().mChildren.indexOf(task2));
+        verify(task, times(1)).onDisplayChanged(any());
     }
 
     @Test
     public void testBounds() {
         final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1);
+        final Task task = createTaskInStack(stack1, 0 /* userId */);
 
         // Check that setting bounds also updates surface position
         Rect bounds = new Rect(10, 10, 100, 200);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 761f73e..aa6c14e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -117,16 +117,16 @@
             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
             int logo, int windowFlags, Configuration overrideConfig, int displayId) {
         final com.android.server.wm.WindowState window;
-        final AppWindowToken atoken;
+        final ActivityRecord activity;
         final WindowManagerService wm = mWmSupplier.get();
         synchronized (wm.mGlobalLock) {
-            atoken = wm.mRoot.getAppWindowToken(appToken);
+            activity = wm.mRoot.getActivityRecord(appToken);
             IWindow iWindow = mock(IWindow.class);
             doReturn(mock(IBinder.class)).when(iWindow).asBinder();
-            window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, atoken,
+            window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, activity,
                     "Starting window", 0 /* ownerId */, false /* internalWindows */, wm,
                     mock(Session.class), iWindow, mPowerManagerWrapper);
-            atoken.startingWindow = window;
+            activity.startingWindow = window;
         }
         if (mRunnableWhenAddingSplashScreen != null) {
             mRunnableWhenAddingSplashScreen.run();
@@ -134,8 +134,8 @@
         }
         return () -> {
             synchronized (wm.mGlobalLock) {
-                atoken.removeChild(window);
-                atoken.startingWindow = null;
+                activity.removeChild(window);
+                activity.startingWindow = null;
             }
         };
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 2e86178..e8a4e90 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -44,10 +44,10 @@
 
     @Test
     public void testFlow() {
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token);
-        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
-        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
+        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity);
+        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity);
 
         // Make sure our handler processed the message.
         waitHandlerIdle(mWm.mH);
@@ -56,14 +56,14 @@
 
     @Test
     public void testMultiple() {
-        final AppWindowToken token1 = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        final AppWindowToken token2 = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token1);
-        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token2);
-        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token1);
-        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(token2);
-        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(token2);
+        final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity1);
+        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity1);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity2);
+        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity1);
+        mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity2);
+        mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity2);
 
         // Make sure our handler processed the message.
         waitHandlerIdle(mWm.mH);
@@ -72,17 +72,17 @@
 
     @Test
     public void testClear() {
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
         mDisplayContent.mUnknownAppVisibilityController.clear();
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
     }
 
     @Test
     public void testAppRemoved() {
-        final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token);
-        mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(token);
+        final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+        mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
+        mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(activity);
         assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 3563feb..8cd97cb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -16,24 +16,24 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
-import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
 
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.DisplayInfo;
 import android.view.Gravity;
-import android.view.IWindow;
 import android.view.WindowManager;
 
 import androidx.test.filters.FlakyTest;
@@ -57,29 +57,11 @@
 @RunWith(WindowTestRunner.class)
 public class WindowFrameTests extends WindowTestsBase {
 
-    private final IWindow mIWindow = new TestIWindow();
     private final Rect mEmptyRect = new Rect();
     private DisplayContent mTestDisplayContent;
 
-    static class FrameTestWindowState extends WindowState {
-        boolean mDockedResizingForTest = false;
-        FrameTestWindowState(WindowManagerService wm, IWindow iWindow, WindowToken windowToken,
-                WindowManager.LayoutParams attrs) {
-            super(wm, mock(Session.class), iWindow, windowToken, null, 0, 0, attrs, 0, 0,
-                    false /* ownerCanAddInternalSystemWindow */);
-        }
-
-        @Override
-        boolean isDockedResizing() {
-            return mDockedResizingForTest;
-        }
-    }
-
-    TaskStack mStubStack;
-
     @Before
     public void setUp() throws Exception {
-        mStubStack = mock(TaskStack.class);
         DisplayInfo testDisplayInfo = new DisplayInfo(mDisplayInfo);
         testDisplayInfo.displayCutout = null;
         mTestDisplayContent = createNewDisplay(testDisplayInfo);
@@ -129,8 +111,7 @@
                 expectedRect.bottom);
     }
 
-    private void assertPolicyCrop(
-            FrameTestWindowState w, int left, int top, int right, int bottom) {
+    private void assertPolicyCrop(WindowState w, int left, int top, int right, int bottom) {
         Rect policyCrop = new Rect();
         w.calculatePolicyCrop(policyCrop);
         assertRect(policyCrop, left, top, right, bottom);
@@ -139,7 +120,7 @@
     @Test
     public void testLayoutInFullscreenTaskInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final int bottomContentInset = 100;
@@ -196,7 +177,7 @@
     @Test
     public void testLayoutInFullscreenTaskNoInsets() {
         // fullscreen task doesn't use bounds for computeFrame
-        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         // With no insets or system decor all the frames incoming from PhoneWindowManager
@@ -278,16 +259,16 @@
         final int logicalWidth = displayInfo.logicalWidth;
         final int logicalHeight = displayInfo.logicalHeight;
 
-        final int taskLeft = logicalWidth / 4;
-        final int taskTop = logicalHeight / 4;
-        final int taskRight = logicalWidth / 4 * 3;
-        final int taskBottom = logicalHeight / 4 * 3;
-        final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
-        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final Rect taskBounds = new Rect(
+                logicalWidth / 4, logicalHeight / 4, logicalWidth / 4 * 3, logicalHeight / 4 * 3);
+        WindowState w = createWindow();
         final Task task = w.getTask();
         // Use split-screen because it is non-fullscreen, but also not floating
-        task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
-        task.setBounds(taskBounds);
+        task.mTaskRecord.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        task.mTaskRecord.setBounds(taskBounds);
+        // The bounds we are requesting might be different from what the system resolved based on
+        // other factors.
+        final Rect resolvedTaskBounds = task.getBounds();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
@@ -296,8 +277,8 @@
         w.computeFrameLw();
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
-        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
-        assertContentFrame(w, taskBounds);
+        assertEquals(resolvedTaskBounds, w.getFrameLw());
+        assertContentFrame(w, resolvedTaskBounds);
         assertContentInset(w, 0, 0, 0, 0);
 
         pf.set(0, 0, logicalWidth, logicalHeight);
@@ -307,36 +288,38 @@
         final Rect cf = new Rect(0, 0, cfRight, cfBottom);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw();
-        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
-        int contentInsetRight = taskRight - cfRight;
-        int contentInsetBottom = taskBottom - cfBottom;
+        assertEquals(resolvedTaskBounds, w.getFrameLw());
+        int contentInsetRight = resolvedTaskBounds.right - cfRight;
+        int contentInsetBottom = resolvedTaskBounds.bottom - cfBottom;
         assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
-        assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
-                taskBottom - contentInsetBottom));
+        assertContentFrame(w, new Rect(resolvedTaskBounds.left, resolvedTaskBounds.top,
+                resolvedTaskBounds.right - contentInsetRight,
+                resolvedTaskBounds.bottom - contentInsetBottom));
 
         pf.set(0, 0, logicalWidth, logicalHeight);
         // If we set displayed bounds, the insets will be computed with the main task bounds
         // but the frame will be positioned according to the displayed bounds.
         final int insetLeft = logicalWidth / 5;
         final int insetTop = logicalHeight / 5;
-        final int insetRight = insetLeft + (taskRight - taskLeft);
-        final int insetBottom = insetTop + (taskBottom - taskTop);
-        task.setOverrideDisplayedBounds(taskBounds);
-        task.setBounds(insetLeft, insetTop, insetRight, insetBottom);
+        final int insetRight = insetLeft + (resolvedTaskBounds.right - resolvedTaskBounds.left);
+        final int insetBottom = insetTop + (resolvedTaskBounds.bottom - resolvedTaskBounds.top);
+        task.mTaskRecord.setDisplayedBounds(resolvedTaskBounds);
+        task.mTaskRecord.setBounds(insetLeft, insetTop, insetRight, insetBottom);
         windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
         w.computeFrameLw();
-        assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
+        assertEquals(resolvedTaskBounds, w.getFrameLw());
         contentInsetRight = insetRight - cfRight;
         contentInsetBottom = insetBottom - cfBottom;
         assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom);
-        assertContentFrame(w, new Rect(taskLeft, taskTop, taskRight - contentInsetRight,
-                taskBottom - contentInsetBottom));
+        assertContentFrame(w, new Rect(resolvedTaskBounds.left, resolvedTaskBounds.top,
+                resolvedTaskBounds.right - contentInsetRight,
+                resolvedTaskBounds.bottom - contentInsetBottom));
     }
 
     @Test
     @FlakyTest(bugId = 130388666)
     public void testCalculatePolicyCrop() {
-        final FrameTestWindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        final WindowState w = createWindow();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
@@ -381,7 +364,7 @@
         // to the computed window frame.
         assertPolicyCrop(w, 0, 0, logicalWidth / 2, logicalHeight / 2);
 
-        w.mDockedResizingForTest = true;
+        doReturn(true).when(w).isDockedResizing();
         // But if we are docked resizing it won't be, however we will still be
         // shrunk to the decor frame and the display.
         assertPolicyCrop(w, 0, 0,
@@ -402,7 +385,7 @@
         final int taskRight = logicalWidth / 4 * 3;
         final int taskBottom = logicalHeight / 4 * 3;
         final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
-        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow();
         final Task task = w.getTask();
         // Use split-screen because it is non-fullscreen, but also not floating
         task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
@@ -422,10 +405,10 @@
         // Now simulate switch to fullscreen for letterboxed app.
         final int xInset = logicalWidth / 10;
         final Rect cf = new Rect(xInset, 0, logicalWidth - xInset, logicalHeight);
-        Configuration config = new Configuration(w.mAppToken.getRequestedOverrideConfiguration());
+        Configuration config = new Configuration(w.mActivityRecord.getRequestedOverrideConfiguration());
         config.windowConfiguration.setBounds(cf);
         config.windowConfiguration.setAppBounds(cf);
-        w.mAppToken.onRequestedOverrideConfigurationChanged(config);
+        w.mActivityRecord.onRequestedOverrideConfigurationChanged(config);
         pf.set(0, 0, logicalWidth, logicalHeight);
         task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         task.setBounds(null);
@@ -440,7 +423,7 @@
     @FlakyTest(bugId = 130388666)
     public void testDisplayCutout() {
         // Regular fullscreen task and window
-        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, 1000, 2000);
@@ -464,7 +447,7 @@
     @FlakyTest(bugId = 130388666)
     public void testDisplayCutout_tempDisplayedBounds() {
         // Regular fullscreen task and window
-        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow();
         final Task task = w.getTask();
         task.setBounds(new Rect(0, 0, 1000, 2000));
         task.setOverrideDisplayedBounds(new Rect(0, -500, 1000, 1500));
@@ -489,11 +472,12 @@
 
     @Test
     public void testFreeformContentInsets() {
+        removeGlobalMinSizeRestriction();
         // fullscreen task doesn't use bounds for computeFrame
-        WindowState w = createWindow(MATCH_PARENT, MATCH_PARENT);
+        WindowState w = createWindow();
         final Task task = w.getTask();
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
-        task.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        task.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
 
         DisplayContent dc = mTestDisplayContent;
         dc.mInputMethodTarget = w;
@@ -515,7 +499,7 @@
         // First check that it only gets moved up enough to show window.
         final Rect winRect = new Rect(200, 200, 300, 500);
 
-        task.setBounds(winRect);
+        task.mTaskRecord.setBounds(winRect);
         w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
         w.computeFrameLw();
 
@@ -527,7 +511,7 @@
 
         // Now check that it won't get moved beyond the top and then has appropriate insets
         winRect.bottom = 600;
-        task.setBounds(winRect);
+        task.mTaskRecord.setBounds(winRect);
         w.setBounds(winRect);
         w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
         w.computeFrameLw();
@@ -544,16 +528,9 @@
         assertEquals(winRect, w.getFrameLw());
     }
 
-    private FrameTestWindowState createWindow(int width, int height) {
-        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
-        attrs.width = width;
-        attrs.height = height;
-
-        AppWindowToken token = createAppWindowToken(mTestDisplayContent,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-
-        FrameTestWindowState ws = new FrameTestWindowState(mWm, mIWindow, token, attrs);
-        token.addWindow(ws);
+    private WindowState createWindow() {
+        final WindowState ws = createWindow(null, TYPE_APPLICATION, mTestDisplayContent, "WindowFrameTests");
+        spyOn(ws);
         return ws;
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index a09253a..98d73ba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -303,11 +303,11 @@
     @Test
     public void testPrepareWindowToDisplayDuringRelayout() {
         // Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON before
-        // calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same appWindowToken.
-        final AppWindowToken appWindowToken = createAppWindowToken(mDisplayContent,
+        // calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same activity.
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        final WindowState first = createWindow(null, TYPE_APPLICATION, appWindowToken, "first");
-        final WindowState second = createWindow(null, TYPE_APPLICATION, appWindowToken, "second");
+        final WindowState first = createWindow(null, TYPE_APPLICATION, activity, "first");
+        final WindowState second = createWindow(null, TYPE_APPLICATION, activity, "second");
         second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
 
         testPrepareWindowToDisplayDuringRelayout(first, false /* expectedWakeupCalled */,
@@ -316,8 +316,8 @@
                 false /* expectedCurrentLaunchCanTurnScreenOn */);
 
         // Call prepareWindowToDisplayDuringRelayout for two window that have FLAG_TURN_SCREEN_ON
-        // from the same appWindowToken. Only one should trigger the wakeup.
-        appWindowToken.setCurrentLaunchCanTurnScreenOn(true);
+        // from the same activity. Only one should trigger the wakeup.
+        activity.setCurrentLaunchCanTurnScreenOn(true);
         first.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
         second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
 
@@ -328,15 +328,15 @@
 
         // Without window flags, the state of ActivityRecord.canTurnScreenOn should still be able to
         // turn on the screen.
-        appWindowToken.setCurrentLaunchCanTurnScreenOn(true);
+        activity.setCurrentLaunchCanTurnScreenOn(true);
         first.mAttrs.flags &= ~WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
-        doReturn(true).when(appWindowToken).canTurnScreenOn();
+        doReturn(true).when(activity).canTurnScreenOn();
 
         testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
                 false /* expectedCurrentLaunchCanTurnScreenOn */);
 
         // Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an
-        // appWindowToken. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
+        // activity. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
         final WindowToken windowToken = WindowTestUtils.createTestWindowToken(FIRST_SUB_WINDOW,
                 mDisplayContent);
         final WindowState firstWindow = createWindow(null, TYPE_APPLICATION, windowToken,
@@ -371,7 +371,7 @@
         }
         // If wakeup is expected to be called, the currentLaunchCanTurnScreenOn should be false
         // because the state will be consumed.
-        assertThat(appWindow.mAppToken.currentLaunchCanTurnScreenOn(),
+        assertThat(appWindow.mActivityRecord.currentLaunchCanTurnScreenOn(),
                 is(expectedCurrentLaunchCanTurnScreenOn));
     }
 
@@ -397,14 +397,15 @@
     }
 
     @Test
-    public void testVisibleWithInsetsProvider() throws Exception {
+    public void testVisibleWithInsetsProvider() {
         final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar");
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         topBar.mHasSurface = true;
         assertTrue(topBar.isVisible());
         mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
-                .setWindow(topBar, null);
-        mDisplayContent.getInsetsStateController().onBarControlTargetChanged(app, app);
+                .setWindow(topBar, null /* frameProvider */);
+        mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
+                app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
         mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
                 .onInsetsModified(app, new InsetsSource(TYPE_TOP_BAR));
         waitUntilHandlersIdle();
@@ -555,7 +556,7 @@
 
         // Mock active recents animation
         RecentsAnimationController recentsController = mock(RecentsAnimationController.class);
-        when(recentsController.isAnimatingTask(win0.mAppToken.getTask())).thenReturn(true);
+        when(recentsController.isAnimatingTask(win0.mActivityRecord.getTask())).thenReturn(true);
         mWm.setRecentsAnimationController(recentsController);
         assertTrue(win0.cantReceiveTouchInput());
     }
@@ -563,14 +564,14 @@
     @Test
     public void testCantReceiveTouchWhenAppTokenHiddenRequested() {
         final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
-        win0.mAppToken.hiddenRequested = true;
+        win0.mActivityRecord.hiddenRequested = true;
         assertTrue(win0.cantReceiveTouchInput());
     }
 
     @Test
     public void testCantReceiveTouchWhenShouldIgnoreInput() {
         final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
-        win0.mAppToken.getStack().setAdjustedForMinimizedDock(1 /* Any non 0 value works */);
+        win0.mActivityRecord.getStack().setAdjustedForMinimizedDock(1 /* Any non 0 value works */);
         assertTrue(win0.cantReceiveTouchInput());
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index f44c969..51daf65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -27,43 +27,59 @@
 import android.view.IWindow;
 import android.view.WindowManager;
 
+import com.android.server.wm.ActivityTestsBase.ActivityBuilder;
+
 /**
  * A collection of static functions that provide access to WindowManager related test functionality.
  */
 class WindowTestUtils {
-    private static int sNextTaskId = 0;
 
     /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
-    static Task createTaskInStack(WindowManagerService service, TaskStack stack,
-            int userId) {
+    static Task createTaskInStack(WindowManagerService service, TaskStack stack, int userId) {
         synchronized (service.mGlobalLock) {
-            final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false,
-                    new ActivityManager.TaskDescription(), null);
-            stack.addTask(newTask, POSITION_TOP);
-            return newTask;
+            final TaskRecord task = new ActivityTestsBase.TaskBuilder(
+                    stack.mActivityStack.mStackSupervisor)
+                    .setUserId(userId)
+                    .setStack(stack.mActivityStack)
+                    .build();
+            return task.mTask;
         }
     }
 
-    /** Creates an {@link AppWindowToken} and adds it to the specified {@link Task}. */
-    static ActivityRecord createAppWindowTokenInTask(DisplayContent dc, Task task) {
-        final ActivityRecord newToken = createTestAppWindowToken(dc);
-        task.addChild(newToken, POSITION_TOP);
-        return newToken;
+    /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
+    static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
+        final ActivityRecord activity = createTestActivityRecord(dc);
+        task.addChild(activity, POSITION_TOP);
+        return activity;
     }
 
-    static ActivityRecord createTestAppWindowToken(DisplayContent dc) {
+    static ActivityRecord createTestActivityRecord(ActivityStack stack) {
+        synchronized (stack.mService.mGlobalLock) {
+            final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(
+                    stack.mService)
+                    .setStack(stack)
+                    .setCreateTask(true)
+                    .build();
+            postCreateActivitySetup(activity, stack.mTaskStack.getDisplayContent());
+            return activity;
+        }
+    }
+
+    static ActivityRecord createTestActivityRecord(DisplayContent dc) {
         synchronized (dc.mWmService.mGlobalLock) {
-            final ActivityRecord r =
-                    new ActivityTestsBase.ActivityBuilder(dc.mWmService.mAtmService)
-                            .build();
-            r.onDisplayChanged(dc);
-            r.setOccludesParent(true);
-            r.setHidden(false);
-            r.hiddenRequested = false;
-            return r;
+            final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
+            postCreateActivitySetup(activity, dc);
+            return activity;
         }
     }
 
+    private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
+        activity.onDisplayChanged(dc);
+        activity.setOccludesParent(true);
+        activity.setHidden(false);
+        activity.hiddenRequested = false;
+    }
+
     static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
         return createTestWindowToken(type, dc, false /* persistOnEmpty */);
     }
@@ -92,49 +108,6 @@
         }
     }
 
-    /* Used so we can gain access to some protected members of the {@link Task} class */
-    static class TestTask extends Task {
-        boolean mShouldDeferRemoval = false;
-        boolean mOnDisplayChangedCalled = false;
-        private boolean mIsAnimating = false;
-
-        TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
-                int resizeMode, boolean supportsPictureInPicture,
-                TaskRecord taskRecord) {
-            super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
-                    new ActivityManager.TaskDescription(), taskRecord);
-            stack.addTask(this, POSITION_TOP);
-        }
-
-        boolean shouldDeferRemoval() {
-            return mShouldDeferRemoval;
-        }
-
-        int positionInParent() {
-            return getParent().mChildren.indexOf(this);
-        }
-
-        @Override
-        void onDisplayChanged(DisplayContent dc) {
-            super.onDisplayChanged(dc);
-            mOnDisplayChangedCalled = true;
-        }
-
-        @Override
-        boolean isSelfAnimating() {
-            return mIsAnimating;
-        }
-
-        void setLocalIsAnimating(boolean isAnimating) {
-            mIsAnimating = isAnimating;
-        }
-    }
-
-    static TestTask createTestTask(TaskStack stack) {
-        return new TestTask(sNextTaskId++, stack, 0, stack.mWmService, RESIZE_MODE_UNRESIZEABLE,
-                false, mock(TaskRecord.class));
-    }
-
     /** Used to track resize reports. */
     static class TestWindowState extends WindowState {
         boolean mResizeReported;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 1fce46c..780fed9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -200,22 +200,18 @@
                 return WindowTestUtils.createTestWindowToken(type, dc);
             }
 
-            return createAppWindowToken(dc, windowingMode, activityType);
+            return createActivityRecord(dc, windowingMode, activityType);
         }
     }
 
-    ActivityRecord createAppWindowToken(DisplayContent dc, int windowingMode, int activityType) {
-        return createTestAppWindowToken(dc, windowingMode, activityType);
+    ActivityRecord createActivityRecord(DisplayContent dc, int windowingMode, int activityType) {
+        return createTestActivityRecord(dc, windowingMode, activityType);
     }
 
-    ActivityRecord createTestAppWindowToken(DisplayContent dc, int
+    ActivityRecord createTestActivityRecord(DisplayContent dc, int
             windowingMode, int activityType) {
         final TaskStack stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
-        final Task task = createTaskInStack(stack, 0 /* userId */);
-        final ActivityRecord appWindowToken =
-                WindowTestUtils.createTestAppWindowToken(dc);
-        task.addChild(appWindowToken, 0);
-        return appWindowToken;
+        return WindowTestUtils.createTestActivityRecord(stack.mActivityStack);
     }
 
     WindowState createWindow(WindowState parent, int type, String name) {
@@ -244,9 +240,10 @@
 
     WindowState createAppWindow(Task task, int type, String name) {
         synchronized (mWm.mGlobalLock) {
-            final ActivityRecord token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
-            task.addChild(token, 0);
-            return createWindow(null, type, token, name);
+            final ActivityRecord activity =
+                    WindowTestUtils.createTestActivityRecord(mDisplayContent);
+            task.addChild(activity, 0);
+            return createWindow(null, type, activity, name);
         }
     }
 
@@ -326,14 +323,14 @@
 
     TaskStack createTaskStackOnDisplay(int windowingMode, int activityType, DisplayContent dc) {
         synchronized (mWm.mGlobalLock) {
-            final Configuration overrideConfig = new Configuration();
-            overrideConfig.windowConfiguration.setWindowingMode(windowingMode);
-            overrideConfig.windowConfiguration.setActivityType(activityType);
-            final int stackId = ++sNextStackId;
-            final TaskStack stack = new TaskStack(mWm, stackId, mock(ActivityStack.class));
-            dc.setStackOnDisplay(stackId, true, stack);
-            stack.onRequestedOverrideConfigurationChanged(overrideConfig);
-            return stack;
+            final ActivityStack stack = new ActivityTestsBase.StackBuilder(
+                    dc.mWmService.mAtmService.mRootActivityContainer)
+                    .setDisplay(dc.mActivityDisplay)
+                    .setWindowingMode(windowingMode)
+                    .setActivityType(activityType)
+                    .setCreateActivity(false)
+                    .build();
+            return stack.mTaskStack;
         }
     }
 
@@ -385,4 +382,9 @@
         displayInfo.ownerUid = SYSTEM_UID;
         return createNewDisplay(displayInfo);
     }
+
+    /** Sets the default minimum task size to 1 so that tests can use small task sizes */
+    public void removeGlobalMinSizeRestriction() {
+        mWm.mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index a783a40..46b261b 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -42,8 +42,12 @@
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.util.proto.ProtoInputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -52,6 +56,8 @@
 import java.util.List;
 
 public class IntervalStats {
+    private static final String TAG = "IntervalStats";
+
     public static final int CURRENT_MAJOR_VERSION = 1;
     public static final int CURRENT_MINOR_VERSION = 1;
     public int majorVersion = CURRENT_MAJOR_VERSION;
@@ -64,6 +70,8 @@
     public final EventTracker keyguardShownTracker = new EventTracker();
     public final EventTracker keyguardHiddenTracker = new EventTracker();
     public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>();
+    /** @hide */
+    public final SparseArray<UsageStats> packageStatsObfuscated = new SparseArray<>();
     public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>();
     public Configuration activeConfiguration;
     public final EventList events = new EventList();
@@ -436,4 +444,234 @@
         */
         majorVersion = CURRENT_MAJOR_VERSION;
     }
+
+    /**
+     * Parses all of the tokens to strings in the obfuscated usage stats data. This includes
+     * deobfuscating each of the package tokens and chooser actions and categories.
+     */
+    private void deobfuscateUsageStats(PackagesTokenData packagesTokenData) {
+        final int usageStatsSize = packageStatsObfuscated.size();
+        for (int statsIndex = 0; statsIndex < usageStatsSize; statsIndex++) {
+            final int packageToken = packageStatsObfuscated.keyAt(statsIndex);
+            final UsageStats usageStats = packageStatsObfuscated.valueAt(statsIndex);
+            usageStats.mPackageName = packagesTokenData.getPackageString(packageToken);
+            if (usageStats.mPackageName == null) {
+                Slog.e(TAG, "Unable to parse usage stats package " + packageToken);
+                continue;
+            }
+
+            // Update chooser counts
+            final int chooserActionsSize = usageStats.mChooserCountsObfuscated.size();
+            for (int actionIndex = 0; actionIndex < chooserActionsSize; actionIndex++) {
+                final ArrayMap<String, Integer> categoryCountsMap = new ArrayMap<>();
+                final int actionToken = usageStats.mChooserCountsObfuscated.keyAt(actionIndex);
+                final String action = packagesTokenData.getString(packageToken, actionToken);
+                if (action == null) {
+                    Slog.i(TAG, "Unable to parse chooser action " + actionToken
+                            + " for package " + packageToken);
+                    continue;
+                }
+                final SparseIntArray categoryCounts =
+                        usageStats.mChooserCountsObfuscated.valueAt(actionIndex);
+                final int categoriesSize = categoryCounts.size();
+                for (int categoryIndex = 0; categoryIndex < categoriesSize; categoryIndex++) {
+                    final int categoryToken = categoryCounts.keyAt(categoryIndex);
+                    final String category = packagesTokenData.getString(packageToken,
+                            categoryToken);
+                    if (category == null) {
+                        Slog.i(TAG, "Unable to parse chooser category " + categoryToken
+                                + " for package " + packageToken);
+                        continue;
+                    }
+                    categoryCountsMap.put(category, categoryCounts.valueAt(categoryIndex));
+                }
+                usageStats.mChooserCounts.put(action, categoryCountsMap);
+            }
+            packageStats.put(usageStats.mPackageName, usageStats);
+        }
+    }
+
+    /**
+     * Parses all of the tokens to strings in the obfuscated events data. This includes
+     * deobfuscating the package token, along with any class, task root package/class tokens, and
+     * shortcut or notification channel tokens.
+     */
+    private void deobfuscateEvents(PackagesTokenData packagesTokenData) {
+        for (int i = this.events.size() - 1; i >= 0; i--) {
+            final Event event = this.events.get(i);
+            final int packageToken = event.mPackageToken;
+            event.mPackage = packagesTokenData.getPackageString(packageToken);
+            if (event.mPackage == null) {
+                Slog.e(TAG, "Unable to parse event package " + packageToken);
+                this.events.remove(i);
+                continue;
+            }
+
+            if (event.mClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                event.mClass = packagesTokenData.getString(packageToken, event.mClassToken);
+                if (event.mClass == null) {
+                    Slog.i(TAG, "Unable to parse class " + event.mClassToken
+                            + " for package " + packageToken);
+                }
+            }
+            if (event.mTaskRootPackageToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                event.mTaskRootPackage = packagesTokenData.getString(packageToken,
+                        event.mTaskRootPackageToken);
+                if (event.mTaskRootPackage == null) {
+                    Slog.i(TAG, "Unable to parse task root package " + event.mTaskRootPackageToken
+                            + " for package " + packageToken);
+                }
+            }
+            if (event.mTaskRootClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                event.mTaskRootClass = packagesTokenData.getString(packageToken,
+                        event.mTaskRootClassToken);
+                if (event.mTaskRootClass == null) {
+                    Slog.i(TAG, "Unable to parse task root class " + event.mTaskRootClassToken
+                            + " for package " + packageToken);
+                }
+            }
+            switch (event.mEventType) {
+                case CONFIGURATION_CHANGE:
+                    if (event.mConfiguration == null) {
+                        event.mConfiguration = new Configuration();
+                    }
+                    break;
+                case SHORTCUT_INVOCATION:
+                    event.mShortcutId = packagesTokenData.getString(packageToken,
+                            event.mShortcutIdToken);
+                    if (event.mShortcutId == null) {
+                        Slog.e(TAG, "Unable to parse shortcut " + event.mShortcutIdToken
+                                + " for package " + packageToken);
+                        this.events.remove(i);
+                        continue;
+                    }
+                    break;
+                case NOTIFICATION_INTERRUPTION:
+                    event.mNotificationChannelId = packagesTokenData.getString(packageToken,
+                            event.mNotificationChannelIdToken);
+                    if (event.mNotificationChannelId == null) {
+                        Slog.e(TAG, "Unable to parse notification channel "
+                                + event.mNotificationChannelIdToken + " for package "
+                                + packageToken);
+                        this.events.remove(i);
+                        continue;
+                    }
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Parses the obfuscated tokenized data held in this interval stats object.
+     *
+     * @hide
+     */
+    public void deobfuscateData(PackagesTokenData packagesTokenData) {
+        deobfuscateUsageStats(packagesTokenData);
+        deobfuscateEvents(packagesTokenData);
+    }
+
+    /**
+     * Obfuscates certain strings within each package stats such as the package name, and the
+     * chooser actions and categories.
+     */
+    private void obfuscateUsageStatsData(PackagesTokenData packagesTokenData) {
+        final int usageStatsSize = packageStats.size();
+        for (int statsIndex = 0; statsIndex < usageStatsSize; statsIndex++) {
+            final String packageName = packageStats.keyAt(statsIndex);
+            final UsageStats usageStats = packageStats.valueAt(statsIndex);
+            if (usageStats == null) {
+                continue;
+            }
+
+            final int packageToken = packagesTokenData.getPackageTokenOrAdd(
+                    packageName, usageStats.mEndTimeStamp);
+            // don't obfuscate stats whose packages have been removed
+            if (packageToken == PackagesTokenData.UNASSIGNED_TOKEN) {
+                continue;
+            }
+            usageStats.mPackageToken = packageToken;
+            // Update chooser counts.
+            final int chooserActionsSize = usageStats.mChooserCounts.size();
+            for (int actionIndex = 0; actionIndex < chooserActionsSize; actionIndex++) {
+                final String action = usageStats.mChooserCounts.keyAt(actionIndex);
+                final ArrayMap<String, Integer> categoriesMap =
+                        usageStats.mChooserCounts.valueAt(actionIndex);
+                if (categoriesMap == null) {
+                    continue;
+                }
+
+                final SparseIntArray categoryCounts = new SparseIntArray();
+                final int categoriesSize = categoriesMap.size();
+                for (int categoryIndex = 0; categoryIndex < categoriesSize; categoryIndex++) {
+                    String category = categoriesMap.keyAt(categoryIndex);
+                    int categoryToken = packagesTokenData.getTokenOrAdd(packageToken, packageName,
+                            category);
+                    categoryCounts.put(categoryToken, categoriesMap.valueAt(categoryIndex));
+                }
+                int actionToken = packagesTokenData.getTokenOrAdd(packageToken, packageName,
+                        action);
+                usageStats.mChooserCountsObfuscated.put(actionToken, categoryCounts);
+            }
+            packageStatsObfuscated.put(packageToken, usageStats);
+        }
+    }
+
+    /**
+     * Obfuscates certain strings within an event such as the package name, the class name,
+     * task root package and class names, and shortcut and notification channel ids.
+     */
+    private void obfuscateEventsData(PackagesTokenData packagesTokenData) {
+        for (int i = events.size() - 1; i >= 0; i--) {
+            final Event event = events.get(i);
+            if (event == null) {
+                continue;
+            }
+
+            final int packageToken = packagesTokenData.getPackageTokenOrAdd(
+                    event.mPackage, event.mTimeStamp);
+            // don't obfuscate events from packages that have been removed
+            if (packageToken == PackagesTokenData.UNASSIGNED_TOKEN) {
+                events.remove(i);
+                continue;
+            }
+            event.mPackageToken = packageToken;
+            if (!TextUtils.isEmpty(event.mClass)) {
+                event.mClassToken = packagesTokenData.getTokenOrAdd(packageToken,
+                        event.mPackage, event.mClass);
+            }
+            if (!TextUtils.isEmpty(event.mTaskRootPackage)) {
+                event.mTaskRootPackageToken = packagesTokenData.getTokenOrAdd(packageToken,
+                        event.mPackage, event.mTaskRootPackage);
+            }
+            if (!TextUtils.isEmpty(event.mTaskRootClass)) {
+                event.mTaskRootClassToken = packagesTokenData.getTokenOrAdd(packageToken,
+                        event.mPackage, event.mTaskRootClass);
+            }
+            switch (event.mEventType) {
+                case SHORTCUT_INVOCATION:
+                    if (!TextUtils.isEmpty(event.mShortcutId)) {
+                        event.mShortcutIdToken = packagesTokenData.getTokenOrAdd(packageToken,
+                                event.mPackage, event.mShortcutId);
+                    }
+                    break;
+                case NOTIFICATION_INTERRUPTION:
+                    if (!TextUtils.isEmpty(event.mNotificationChannelId)) {
+                        event.mNotificationChannelIdToken = packagesTokenData.getTokenOrAdd(
+                                packageToken, event.mPackage, event.mNotificationChannelId);
+                    }
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Obfuscates the data in this instance of interval stats.
+     *
+     * @hide
+     */
+    public void obfuscateData(PackagesTokenData packagesTokenData) {
+        obfuscateUsageStatsData(packagesTokenData);
+        obfuscateEventsData(packagesTokenData);
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/PackagesTokenData.java b/services/usage/java/com/android/server/usage/PackagesTokenData.java
new file mode 100644
index 0000000..4bf08a4
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/PackagesTokenData.java
@@ -0,0 +1,176 @@
+/*
+ * 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 com.android.server.usage;
+
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import java.util.ArrayList;
+
+/**
+ * An object holding data defining the obfuscated packages and their token mappings.
+ * Used by {@link UsageStatsDatabase}.
+ *
+ * @hide
+ */
+public final class PackagesTokenData {
+    /**
+     * The package name is always stored at index 0 in {@code tokensToPackagesMap}.
+     */
+    private static final int PACKAGE_NAME_INDEX = 0;
+
+    /**
+     * The default token for any string that hasn't been tokenized yet.
+     */
+    public static final int UNASSIGNED_TOKEN = -1;
+
+    /**
+     * The main token counter for each package.
+     */
+    public int counter = 1;
+    /**
+     * Stores a hierarchy of token to string mappings for each package, indexed by the main
+     * package token. The 0th index within the array list will always hold the package name.
+     */
+    public final SparseArray<ArrayList<String>> tokensToPackagesMap = new SparseArray<>();
+    /**
+     * Stores a hierarchy of strings to token mappings for each package. This is simply an inverse
+     * map of the {@code tokenToPackagesMap} in this class, mainly for an O(1) access to the tokens.
+     */
+    public final ArrayMap<String, ArrayMap<String, Integer>> packagesToTokensMap = new ArrayMap<>();
+    /**
+     * Stores a map of packages that were removed and when they were removed.
+     */
+    public final ArrayMap<String, Long> removedPackagesMap = new ArrayMap<>();
+
+    public PackagesTokenData() {
+    }
+
+    /**
+     * Fetches the token mapped to the given package name. If there is no mapping, a new token is
+     * created and the relevant mappings are updated.
+     *
+     * @param packageName the package name whose token is being fetched
+     * @param timeStamp the time stamp of the event or end time of the usage stats; used to verify
+     *                  the package hasn't been removed
+     * @return the mapped token
+     */
+    public int getPackageTokenOrAdd(String packageName, long timeStamp) {
+        final Long timeRemoved = removedPackagesMap.get(packageName);
+        if (timeRemoved != null && timeRemoved > timeStamp) {
+            return UNASSIGNED_TOKEN; // package was removed
+            /*
+             Note: instead of querying Package Manager each time for a list of packages to verify
+             if this package is still installed, it's more efficient to check the internal list of
+             removed packages and verify with the incoming time stamp. Although rare, it is possible
+             that some asynchronous function is triggered after a package is removed and the
+             time stamp passed into this function is not accurate. We'll have to keep the respective
+             event/usage stat until the next time the device reboots and the mappings are cleaned.
+             Additionally, this is a data class with some helper methods - it doesn't make sense to
+             overload it with references to other services.
+             */
+        }
+
+        ArrayMap<String, Integer> packageTokensMap = packagesToTokensMap.get(packageName);
+        if (packageTokensMap == null) {
+            packageTokensMap = new ArrayMap<>();
+            packagesToTokensMap.put(packageName, packageTokensMap);
+        }
+        int token = packageTokensMap.getOrDefault(packageName, UNASSIGNED_TOKEN);
+        if (token == UNASSIGNED_TOKEN) {
+            token = counter++;
+            // package name should always be at index 0 in the sub-mapping
+            ArrayList<String> tokenPackages = new ArrayList<>();
+            tokenPackages.add(packageName);
+            packageTokensMap.put(packageName, token);
+            tokensToPackagesMap.put(token, tokenPackages);
+        }
+        return token;
+    }
+
+    /**
+     * Fetches the token mapped to the given key within the package's context. If there is no
+     * mapping, a new token is created and the relevant mappings are updated.
+     *
+     * @param packageToken the package token for which the given key belongs to
+     * @param packageName the package name for which the given key belongs to
+     * @param key the key whose token is being fetched
+     * @return the mapped token
+     */
+    public int getTokenOrAdd(int packageToken, String packageName, String key) {
+        if (packageName.equals(key)) {
+            return PACKAGE_NAME_INDEX;
+        }
+        int token = packagesToTokensMap.get(packageName).getOrDefault(key, UNASSIGNED_TOKEN);
+        if (token == UNASSIGNED_TOKEN) {
+            token = tokensToPackagesMap.get(packageToken).size();
+            packagesToTokensMap.get(packageName).put(key, token);
+            tokensToPackagesMap.get(packageToken).add(key);
+        }
+        return token;
+    }
+
+    /**
+     * Fetches the package name for the given token.
+     *
+     * @param packageToken the package token representing the package name
+     * @return the string representing the given token or {@code null} if not found
+     */
+    public String getPackageString(int packageToken) {
+        final ArrayList<String> packageStrings = tokensToPackagesMap.get(packageToken);
+        if (packageStrings == null) {
+            return null;
+        }
+        return packageStrings.get(PACKAGE_NAME_INDEX);
+    }
+
+    /**
+     * Fetches the string represented by the given token.
+     *
+     * @param packageToken the package token for which this token belongs to
+     * @param token the token whose string needs to be fetched
+     * @return the string representing the given token or {@code null} if not found
+     */
+    public String getString(int packageToken, int token) {
+        try {
+            return tokensToPackagesMap.get(packageToken).get(token);
+        } catch (NullPointerException npe) {
+            Slog.e("PackagesTokenData",
+                    "Unable to find tokenized strings for package " + packageToken, npe);
+            return null;
+        } catch (IndexOutOfBoundsException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Removes the package from all known mappings.
+     *
+     * @param packageName the package to be removed
+     * @param timeRemoved the time stamp of when the package was removed
+     */
+    public void removePackage(String packageName, long timeRemoved) {
+        removedPackagesMap.put(packageName, timeRemoved);
+
+        if (!packagesToTokensMap.containsKey(packageName)) {
+            return;
+        }
+        final int packageToken = packagesToTokensMap.get(packageName).get(packageName);
+        packagesToTokensMap.remove(packageName);
+        tokensToPackagesMap.delete(packageToken);
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 5197b3b..db7ed1f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -17,12 +17,15 @@
 package com.android.server.usage;
 
 import android.app.usage.TimeSparseArray;
+import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.os.Build;
 import android.os.SystemProperties;
+import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.TimeUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -75,7 +78,7 @@
  * directory should be deserialized.
  */
 public class UsageStatsDatabase {
-    private static final int DEFAULT_CURRENT_VERSION = 4;
+    private static final int DEFAULT_CURRENT_VERSION = 5;
     /**
      * Current version of the backup schema
      *
@@ -93,7 +96,8 @@
 
     // Persist versioned backup files.
     // Should be false, except when testing new versions
-    static final boolean KEEP_BACKUP_DIR = false;
+    // STOPSHIP: b/139937606 this should be false on launch
+    static final boolean KEEP_BACKUP_DIR = true;
 
     private static final String TAG = "UsageStatsDatabase";
     private static final boolean DEBUG = UsageStatsService.DEBUG;
@@ -119,6 +123,11 @@
     private boolean mFirstUpdate;
     private boolean mNewUpdate;
 
+    // The obfuscated packages to tokens mappings file
+    private final File mPackageMappingsFile;
+    // Holds all of the data related to the obfuscated packages and their token mappings.
+    final PackagesTokenData mPackagesTokenData = new PackagesTokenData();
+
     /**
      * UsageStatsDatabase constructor that allows setting the version number.
      * This should only be used for testing.
@@ -138,6 +147,7 @@
         mBackupsDir = new File(dir, "backups");
         mUpdateBreadcrumb = new File(dir, "breadcrumb");
         mSortedStatFiles = new TimeSparseArray[mIntervalDirs.length];
+        mPackageMappingsFile = new File(dir, "mappings");
         mCal = new UnixCalendar(0);
     }
 
@@ -479,6 +489,11 @@
     private void continueUpgradeLocked(int version, long token) {
         final File backupDir = new File(mBackupsDir, Long.toString(token));
 
+        // Upgrade step logic for the entire usage stats directory, not individual interval dirs.
+        if (version >= 5) {
+            readMappingsLocked();
+        }
+
         // Read each file in the backup according to the version and write to the interval
         // directories in the current versions format
         for (int i = 0; i < mIntervalDirs.length; i++) {
@@ -494,9 +509,16 @@
                     }
                     try {
                         IntervalStats stats = new IntervalStats();
-                        readLocked(new AtomicFile(files[j]), stats, version);
+                        readLocked(new AtomicFile(files[j]), stats, version, mPackagesTokenData);
+                        // Upgrade to version 5+.
+                        // Future version upgrades should add additional logic here to upgrade.
+                        if (mCurrentVersion >= 5) {
+                            // Create the initial obfuscated packages map.
+                            stats.obfuscateData(mPackagesTokenData);
+                        }
                         writeLocked(new AtomicFile(new File(mIntervalDirs[i],
-                                Long.toString(stats.beginTime))), stats, mCurrentVersion);
+                                Long.toString(stats.beginTime))), stats, mCurrentVersion,
+                                mPackagesTokenData);
                     } catch (Exception e) {
                         // This method is called on boot, log the exception and move on
                         Slog.e(TAG, "Failed to upgrade backup file : " + files[j].toString());
@@ -504,6 +526,21 @@
                 }
             }
         }
+
+        // Upgrade step logic for the entire usage stats directory, not individual interval dirs.
+        if (mCurrentVersion >= 5) {
+            try {
+                writeMappingsLocked();
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to write the tokens mappings file.");
+            }
+        }
+    }
+
+    void onPackageRemoved(String packageName, long timeRemoved) {
+        synchronized (mLock) {
+            mPackagesTokenData.removePackage(packageName, timeRemoved);
+        }
     }
 
     public void onTimeChanged(long timeDiffMillis) {
@@ -580,6 +617,37 @@
     }
 
     /**
+     * Filter out those stats from the given stats that belong to removed packages. Filtering out
+     * all of the stats at once has an amortized cost for future calls.
+     */
+    void filterStats(IntervalStats stats) {
+        if (mPackagesTokenData.removedPackagesMap.isEmpty()) {
+            return;
+        }
+        final ArrayMap<String, Long> removedPackagesMap = mPackagesTokenData.removedPackagesMap;
+
+        // filter out package usage stats
+        final int removedPackagesSize = removedPackagesMap.size();
+        for (int i = 0; i < removedPackagesSize; i++) {
+            final String removedPackage = removedPackagesMap.keyAt(i);
+            final UsageStats usageStats = stats.packageStats.get(removedPackage);
+            if (usageStats != null && usageStats.mEndTimeStamp < removedPackagesMap.valueAt(i)) {
+                stats.packageStats.remove(removedPackage);
+            }
+        }
+
+        // filter out events
+        final int eventsSize = stats.events.size();
+        for (int i = stats.events.size() - 1; i >= 0; i--) {
+            final UsageEvents.Event event = stats.events.get(i);
+            final Long timeRemoved = removedPackagesMap.get(event.mPackage);
+            if (timeRemoved != null && timeRemoved > event.mTimeStamp) {
+                stats.events.remove(i);
+            }
+        }
+    }
+
+    /**
      * Figures out what to extract from the given IntervalStats object.
      */
     public interface StatCombiner<T> {
@@ -808,14 +876,14 @@
     }
 
     private void writeLocked(AtomicFile file, IntervalStats stats) throws IOException {
-        writeLocked(file, stats, mCurrentVersion);
+        writeLocked(file, stats, mCurrentVersion, mPackagesTokenData);
     }
 
-    private static void writeLocked(AtomicFile file, IntervalStats stats, int version)
-            throws IOException {
+    private static void writeLocked(AtomicFile file, IntervalStats stats, int version,
+            PackagesTokenData packagesTokenData) throws IOException {
         FileOutputStream fos = file.startWrite();
         try {
-            writeLocked(fos, stats, version);
+            writeLocked(fos, stats, version, packagesTokenData);
             file.finishWrite(fos);
             fos = null;
         } finally {
@@ -825,11 +893,11 @@
     }
 
     private void writeLocked(OutputStream out, IntervalStats stats) throws IOException {
-        writeLocked(out, stats, mCurrentVersion);
+        writeLocked(out, stats, mCurrentVersion, mPackagesTokenData);
     }
 
-    private static void writeLocked(OutputStream out, IntervalStats stats, int version)
-            throws IOException {
+    private static void writeLocked(OutputStream out, IntervalStats stats, int version,
+            PackagesTokenData packagesTokenData) throws IOException {
         switch (version) {
             case 1:
             case 2:
@@ -837,7 +905,19 @@
                 UsageStatsXml.write(out, stats);
                 break;
             case 4:
-                UsageStatsProto.write(out, stats);
+                try {
+                    UsageStatsProto.write(out, stats);
+                } catch (IOException | IllegalArgumentException e) {
+                    Slog.e(TAG, "Unable to write interval stats to proto.", e);
+                }
+                break;
+            case 5:
+                stats.obfuscateData(packagesTokenData);
+                try {
+                    UsageStatsProtoV2.write(out, stats);
+                } catch (IOException | IllegalArgumentException e) {
+                    Slog.e(TAG, "Unable to write interval stats to proto.", e);
+                }
                 break;
             default:
                 throw new RuntimeException(
@@ -847,16 +927,16 @@
     }
 
     private void readLocked(AtomicFile file, IntervalStats statsOut) throws IOException {
-        readLocked(file, statsOut, mCurrentVersion);
+        readLocked(file, statsOut, mCurrentVersion, mPackagesTokenData);
     }
 
-    private static void readLocked(AtomicFile file, IntervalStats statsOut, int version)
-            throws IOException {
+    private static void readLocked(AtomicFile file, IntervalStats statsOut, int version,
+            PackagesTokenData packagesTokenData) throws IOException {
         try {
             FileInputStream in = file.openRead();
             try {
                 statsOut.beginTime = parseBeginTime(file);
-                readLocked(in, statsOut, version);
+                readLocked(in, statsOut, version, packagesTokenData);
                 statsOut.lastTimeSaved = file.getLastModifiedTime();
             } finally {
                 try {
@@ -872,11 +952,11 @@
     }
 
     private void readLocked(InputStream in, IntervalStats statsOut) throws IOException {
-        readLocked(in, statsOut, mCurrentVersion);
+        readLocked(in, statsOut, mCurrentVersion, mPackagesTokenData);
     }
 
-    private static void readLocked(InputStream in, IntervalStats statsOut, int version)
-            throws IOException {
+    private static void readLocked(InputStream in, IntervalStats statsOut, int version,
+            PackagesTokenData packagesTokenData) throws IOException {
         switch (version) {
             case 1:
             case 2:
@@ -884,7 +964,19 @@
                 UsageStatsXml.read(in, statsOut);
                 break;
             case 4:
-                UsageStatsProto.read(in, statsOut);
+                try {
+                    UsageStatsProto.read(in, statsOut);
+                } catch (IOException e) {
+                    Slog.e(TAG, "Unable to read interval stats from proto.", e);
+                }
+                break;
+            case 5:
+                try {
+                    UsageStatsProtoV2.read(in, statsOut);
+                } catch (IOException e) {
+                    Slog.e(TAG, "Unable to read interval stats from proto.", e);
+                }
+                statsOut.deobfuscateData(packagesTokenData);
                 break;
             default:
                 throw new RuntimeException(
@@ -895,6 +987,63 @@
     }
 
     /**
+     * Reads the obfuscated data file from disk containing the tokens to packages mappings and
+     * rebuilds the packages to tokens mappings based on that data.
+     */
+    public void readMappingsLocked() {
+        if (!mPackageMappingsFile.exists()) {
+            return; // package mappings file is missing - recreate mappings on next write.
+        }
+
+        try (FileInputStream in = new AtomicFile(mPackageMappingsFile).openRead()) {
+            UsageStatsProtoV2.readObfuscatedData(in, mPackagesTokenData);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read the obfuscated packages mapping file.", e);
+            return;
+        }
+
+        final SparseArray<ArrayList<String>> tokensToPackagesMap =
+                mPackagesTokenData.tokensToPackagesMap;
+        final int tokensToPackagesMapSize = tokensToPackagesMap.size();
+        for (int i = 0; i < tokensToPackagesMapSize; i++) {
+            final int packageToken = tokensToPackagesMap.keyAt(i);
+            final ArrayList<String> tokensMap = tokensToPackagesMap.valueAt(i);
+            final ArrayMap<String, Integer> packageStringsMap = new ArrayMap<>();
+            final int tokensMapSize = tokensMap.size();
+            // package name will always be at index 0 but its token should not be 0
+            packageStringsMap.put(tokensMap.get(0), packageToken);
+            for (int j = 1; j < tokensMapSize; j++) {
+                packageStringsMap.put(tokensMap.get(j), j);
+            }
+            mPackagesTokenData.packagesToTokensMap.put(tokensMap.get(0), packageStringsMap);
+        }
+    }
+
+    void writeMappingsLocked() throws IOException {
+        final AtomicFile file = new AtomicFile(mPackageMappingsFile);
+        FileOutputStream fos = file.startWrite();
+        try {
+            UsageStatsProtoV2.writeObfuscatedData(fos, mPackagesTokenData);
+            file.finishWrite(fos);
+            fos = null;
+        } catch (IOException | IllegalArgumentException e) {
+            Slog.e(TAG, "Unable to write obfuscated data to proto.", e);
+        } finally {
+            file.failWrite(fos);
+        }
+    }
+
+    void obfuscateCurrentStats(IntervalStats[] currentStats) {
+        if (mCurrentVersion < 5) {
+            return;
+        }
+        for (int i = 0; i < currentStats.length; i++) {
+            final IntervalStats stats = currentStats[i];
+            stats.obfuscateData(mPackagesTokenData);
+        }
+    }
+
+    /**
      * Update the stats in the database. They may not be written to disk immediately.
      */
     public void putUsageStats(int intervalType, IntervalStats stats) throws IOException {
@@ -1098,7 +1247,7 @@
         DataOutputStream out = new DataOutputStream(baos);
         try {
             out.writeLong(stats.beginTime);
-            writeLocked(out, stats, version);
+            writeLocked(out, stats, version, mPackagesTokenData);
         } catch (Exception ioe) {
             Slog.d(TAG, "Serializing IntervalStats Failed", ioe);
             baos.reset();
@@ -1112,7 +1261,7 @@
         IntervalStats stats = new IntervalStats();
         try {
             stats.beginTime = in.readLong();
-            readLocked(in, stats, version);
+            readLocked(in, stats, version, mPackagesTokenData);
         } catch (IOException ioe) {
             Slog.d(TAG, "DeSerializing IntervalStats Failed", ioe);
             stats = null;
@@ -1142,13 +1291,18 @@
     }
 
     /**
-     * print total number and list of stats files for each interval type.
-     * @param pw
+     * Prints the obfuscated package mappings and a summary of the database files.
+     * @param pw the print writer to print to
      */
     public void dump(IndentingPrintWriter pw, boolean compact) {
         synchronized (mLock) {
+            pw.println();
             pw.println("UsageStatsDatabase:");
             pw.increaseIndent();
+            dumpMappings(pw);
+            pw.decreaseIndent();
+            pw.println("Database Summary:");
+            pw.increaseIndent();
             for (int i = 0; i < mSortedStatFiles.length; i++) {
                 final TimeSparseArray<AtomicFile> files = mSortedStatFiles[i];
                 final int size = files.size();
@@ -1173,6 +1327,23 @@
         }
     }
 
+    void dumpMappings(IndentingPrintWriter pw) {
+        synchronized (mLock) {
+            pw.println("Obfuscated Packages Mappings:");
+            pw.increaseIndent();
+            pw.println("Counter: " + mPackagesTokenData.counter);
+            pw.println("Tokens Map Size: " + mPackagesTokenData.tokensToPackagesMap.size());
+            for (int i = 0; i < mPackagesTokenData.tokensToPackagesMap.size(); i++) {
+                final int packageToken = mPackagesTokenData.tokensToPackagesMap.keyAt(i);
+                final String packageStrings = String.join(", ",
+                        mPackagesTokenData.tokensToPackagesMap.valueAt(i));
+                pw.println("Token " + packageToken + ": [" + packageStrings + "]");
+            }
+            pw.println();
+            pw.decreaseIndent();
+        }
+    }
+
     IntervalStats readIntervalStatsForFile(int interval, long fileName) {
         synchronized (mLock) {
             final IntervalStats stats = new IntervalStats();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 6d3f416..87e077e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -120,10 +120,14 @@
                             IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT);
                     break;
                 case (int) IntervalStatsProto.UsageStats.CHOOSER_ACTIONS:
-                    final long chooserToken = proto.start(
-                            IntervalStatsProto.UsageStats.CHOOSER_ACTIONS);
-                    loadChooserCounts(proto, stats);
-                    proto.end(chooserToken);
+                    try {
+                        final long chooserToken = proto.start(
+                                IntervalStatsProto.UsageStats.CHOOSER_ACTIONS);
+                        loadChooserCounts(proto, stats);
+                        proto.end(chooserToken);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read chooser counts for " + stats.mPackageName, e);
+                    }
                     break;
                 case (int) IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS:
                     // Time attributes stored is an offset of the beginTime.
@@ -153,20 +157,24 @@
     }
 
     private static void loadCountAndTime(ProtoInputStream proto, long fieldId,
-            IntervalStats.EventTracker tracker) throws IOException {
-        final long token = proto.start(fieldId);
-        while (true) {
-            switch (proto.nextField()) {
-                case (int) IntervalStatsProto.CountAndTime.COUNT:
-                    tracker.count = proto.readInt(IntervalStatsProto.CountAndTime.COUNT);
-                    break;
-                case (int) IntervalStatsProto.CountAndTime.TIME_MS:
-                    tracker.duration = proto.readLong(IntervalStatsProto.CountAndTime.TIME_MS);
-                    break;
-                case ProtoInputStream.NO_MORE_FIELDS:
-                    proto.end(token);
-                    return;
+            IntervalStats.EventTracker tracker) {
+        try {
+            final long token = proto.start(fieldId);
+            while (true) {
+                switch (proto.nextField()) {
+                    case (int) IntervalStatsProto.CountAndTime.COUNT:
+                        tracker.count = proto.readInt(IntervalStatsProto.CountAndTime.COUNT);
+                        break;
+                    case (int) IntervalStatsProto.CountAndTime.TIME_MS:
+                        tracker.duration = proto.readLong(IntervalStatsProto.CountAndTime.TIME_MS);
+                        break;
+                    case ProtoInputStream.NO_MORE_FIELDS:
+                        proto.end(token);
+                        return;
+                }
             }
+        } catch (IOException e) {
+            Slog.e(TAG, "Unable to read event tracker " + fieldId, e);
         }
     }
 
@@ -306,7 +314,7 @@
     }
 
     private static void writeStringPool(ProtoOutputStream proto, final IntervalStats stats)
-            throws IOException {
+            throws IllegalArgumentException {
         final long token = proto.start(IntervalStatsProto.STRINGPOOL);
         final int size = stats.mStringCache.size();
         proto.write(IntervalStatsProto.StringPool.SIZE, size);
@@ -317,7 +325,8 @@
     }
 
     private static void writeUsageStats(ProtoOutputStream proto, long fieldId,
-            final IntervalStats stats, final UsageStats usageStats) throws IOException {
+            final IntervalStats stats, final UsageStats usageStats)
+            throws IllegalArgumentException {
         final long token = proto.start(fieldId);
         // Write the package name first, so loadUsageStats can avoid creating an extra object
         final int packageIndex = stats.mStringCache.indexOf(usageStats.mPackageName);
@@ -325,8 +334,6 @@
             proto.write(IntervalStatsProto.UsageStats.PACKAGE_INDEX, packageIndex + 1);
         } else {
             // Package not in Stringpool for some reason, write full string instead
-            Slog.w(TAG, "UsageStats package name (" + usageStats.mPackageName
-                    + ") not found in IntervalStats string cache");
             proto.write(IntervalStatsProto.UsageStats.PACKAGE, usageStats.mPackageName);
         }
         // Time attributes stored as an offset of the beginTime.
@@ -347,12 +354,16 @@
         proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS,
                 usageStats.mTotalTimeVisible);
         proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
-        writeChooserCounts(proto, usageStats);
+        try {
+            writeChooserCounts(proto, usageStats);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Unable to write chooser counts for " + usageStats.mPackageName, e);
+        }
         proto.end(token);
     }
 
     private static void writeCountAndTime(ProtoOutputStream proto, long fieldId, int count,
-            long time) throws IOException {
+            long time) throws IllegalArgumentException {
         final long token = proto.start(fieldId);
         proto.write(IntervalStatsProto.CountAndTime.COUNT, count);
         proto.write(IntervalStatsProto.CountAndTime.TIME_MS, time);
@@ -361,7 +372,7 @@
 
 
     private static void writeChooserCounts(ProtoOutputStream proto, final UsageStats usageStats)
-            throws IOException {
+            throws IllegalArgumentException {
         if (usageStats == null || usageStats.mChooserCounts == null
                 || usageStats.mChooserCounts.keySet().isEmpty()) {
             return;
@@ -381,7 +392,7 @@
     }
 
     private static void writeCountsForAction(ProtoOutputStream proto,
-            ArrayMap<String, Integer> counts) throws IOException {
+            ArrayMap<String, Integer> counts) throws IllegalArgumentException {
         final int countsSize = counts.size();
         for (int i = 0; i < countsSize; i++) {
             String key = counts.keyAt(i);
@@ -397,7 +408,7 @@
 
     private static void writeConfigStats(ProtoOutputStream proto, long fieldId,
             final IntervalStats stats, final ConfigurationStats configStats, boolean isActive)
-            throws IOException {
+            throws IllegalArgumentException {
         final long token = proto.start(fieldId);
         configStats.mConfiguration.writeToProto(proto, IntervalStatsProto.Configuration.CONFIG);
         proto.write(IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS,
@@ -407,19 +418,16 @@
         proto.write(IntervalStatsProto.Configuration.COUNT, configStats.mActivationCount);
         proto.write(IntervalStatsProto.Configuration.ACTIVE, isActive);
         proto.end(token);
-
     }
 
     private static void writeEvent(ProtoOutputStream proto, long fieldId, final IntervalStats stats,
-            final UsageEvents.Event event) throws IOException {
+            final UsageEvents.Event event) throws IllegalArgumentException {
         final long token = proto.start(fieldId);
         final int packageIndex = stats.mStringCache.indexOf(event.mPackage);
         if (packageIndex >= 0) {
             proto.write(IntervalStatsProto.Event.PACKAGE_INDEX, packageIndex + 1);
         } else {
             // Package not in Stringpool for some reason, write full string instead
-            Slog.w(TAG, "Usage event package name (" + event.mPackage
-                    + ") not found in IntervalStats string cache");
             proto.write(IntervalStatsProto.Event.PACKAGE, event.mPackage);
         }
         if (event.mClass != null) {
@@ -428,8 +436,6 @@
                 proto.write(IntervalStatsProto.Event.CLASS_INDEX, classIndex + 1);
             } else {
                 // Class not in Stringpool for some reason, write full string instead
-                Slog.w(TAG, "Usage event class name (" + event.mClass
-                        + ") not found in IntervalStats string cache");
                 proto.write(IntervalStatsProto.Event.CLASS, event.mClass);
             }
         }
@@ -442,10 +448,6 @@
             if (taskRootPackageIndex >= 0) {
                 proto.write(IntervalStatsProto.Event.TASK_ROOT_PACKAGE_INDEX,
                         taskRootPackageIndex + 1);
-            } else {
-                // Task root package not in Stringpool for some reason.
-                Slog.w(TAG, "Usage event task root package name (" + event.mTaskRootPackage
-                        + ") not found in IntervalStats string cache");
             }
         }
         if (event.mTaskRootClass != null) {
@@ -453,10 +455,6 @@
             if (taskRootClassIndex >= 0) {
                 proto.write(IntervalStatsProto.Event.TASK_ROOT_CLASS_INDEX,
                         taskRootClassIndex + 1);
-            } else {
-                // Task root class not in Stringpool for some reason.
-                Slog.w(TAG, "Usage event task root class name (" + event.mTaskRootClass
-                        + ") not found in IntervalStats string cache");
             }
         }
         switch (event.mEventType) {
@@ -484,9 +482,6 @@
                                 channelIndex + 1);
                     } else {
                         // Channel not in Stringpool for some reason, write full string instead
-                        Slog.w(TAG, "Usage event notification channel name ("
-                                + event.mNotificationChannelId
-                                + ") not found in IntervalStats string cache");
                         proto.write(IntervalStatsProto.Event.NOTIFICATION_CHANNEL,
                                 event.mNotificationChannelId);
                     }
@@ -542,17 +537,33 @@
                             statsOut.keyguardHiddenTracker);
                     break;
                 case (int) IntervalStatsProto.STRINGPOOL:
-                    stringPool = readStringPool(proto);
-                    statsOut.mStringCache.addAll(stringPool);
+                    try {
+                        stringPool = readStringPool(proto);
+                        statsOut.mStringCache.addAll(stringPool);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read string pool from proto.", e);
+                    }
                     break;
                 case (int) IntervalStatsProto.PACKAGES:
-                    loadUsageStats(proto, IntervalStatsProto.PACKAGES, statsOut, stringPool);
+                    try {
+                        loadUsageStats(proto, IntervalStatsProto.PACKAGES, statsOut, stringPool);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read some usage stats from proto.", e);
+                    }
                     break;
                 case (int) IntervalStatsProto.CONFIGURATIONS:
-                    loadConfigStats(proto, IntervalStatsProto.CONFIGURATIONS, statsOut);
+                    try {
+                        loadConfigStats(proto, IntervalStatsProto.CONFIGURATIONS, statsOut);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read some configuration stats from proto.", e);
+                    }
                     break;
                 case (int) IntervalStatsProto.EVENT_LOG:
-                    loadEvent(proto, IntervalStatsProto.EVENT_LOG, statsOut, stringPool);
+                    try {
+                        loadEvent(proto, IntervalStatsProto.EVENT_LOG, statsOut, stringPool);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read some events from proto.", e);
+                    }
                     break;
                 case ProtoInputStream.NO_MORE_FIELDS:
                     if (statsOut.endTime == 0) {
@@ -571,72 +582,60 @@
      * @param proto The serializer to which to write the packageStats data.
      * @param stats The stats object to write to the XML file.
      */
-    public static void write(OutputStream out, IntervalStats stats) throws IOException {
+    public static void write(OutputStream out, IntervalStats stats)
+            throws IOException, IllegalArgumentException {
         final ProtoOutputStream proto = new ProtoOutputStream(out);
         proto.write(IntervalStatsProto.END_TIME_MS, stats.endTime - stats.beginTime);
         proto.write(IntervalStatsProto.MAJOR_VERSION, stats.majorVersion);
         proto.write(IntervalStatsProto.MINOR_VERSION, stats.minorVersion);
         // String pool should be written before the rest of the usage stats
-        writeStringPool(proto, stats);
+        try {
+            writeStringPool(proto, stats);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Unable to write string pool to proto.", e);
+        }
 
-        writeCountAndTime(proto, IntervalStatsProto.INTERACTIVE, stats.interactiveTracker.count,
-                stats.interactiveTracker.duration);
-        writeCountAndTime(proto, IntervalStatsProto.NON_INTERACTIVE,
-                stats.nonInteractiveTracker.count, stats.nonInteractiveTracker.duration);
-        writeCountAndTime(proto, IntervalStatsProto.KEYGUARD_SHOWN,
-                stats.keyguardShownTracker.count, stats.keyguardShownTracker.duration);
-        writeCountAndTime(proto, IntervalStatsProto.KEYGUARD_HIDDEN,
-                stats.keyguardHiddenTracker.count, stats.keyguardHiddenTracker.duration);
+        try {
+            writeCountAndTime(proto, IntervalStatsProto.INTERACTIVE, stats.interactiveTracker.count,
+                    stats.interactiveTracker.duration);
+            writeCountAndTime(proto, IntervalStatsProto.NON_INTERACTIVE,
+                    stats.nonInteractiveTracker.count, stats.nonInteractiveTracker.duration);
+            writeCountAndTime(proto, IntervalStatsProto.KEYGUARD_SHOWN,
+                    stats.keyguardShownTracker.count, stats.keyguardShownTracker.duration);
+            writeCountAndTime(proto, IntervalStatsProto.KEYGUARD_HIDDEN,
+                    stats.keyguardHiddenTracker.count, stats.keyguardHiddenTracker.duration);
+        }  catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Unable to write some interval stats trackers to proto.", e);
+        }
 
         final int statsCount = stats.packageStats.size();
         for (int i = 0; i < statsCount; i++) {
-            writeUsageStats(proto, IntervalStatsProto.PACKAGES, stats,
-                    stats.packageStats.valueAt(i));
+            try {
+                writeUsageStats(proto, IntervalStatsProto.PACKAGES, stats,
+                        stats.packageStats.valueAt(i));
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Unable to write some usage stats to proto.", e);
+            }
         }
         final int configCount = stats.configurations.size();
         for (int i = 0; i < configCount; i++) {
             boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i));
-            writeConfigStats(proto, IntervalStatsProto.CONFIGURATIONS, stats,
-                    stats.configurations.valueAt(i), active);
+            try {
+                writeConfigStats(proto, IntervalStatsProto.CONFIGURATIONS, stats,
+                        stats.configurations.valueAt(i), active);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Unable to write some configuration stats to proto.", e);
+            }
         }
         final int eventCount = stats.events.size();
         for (int i = 0; i < eventCount; i++) {
-            writeEvent(proto, IntervalStatsProto.EVENT_LOG, stats, stats.events.get(i));
-        }
-
-        proto.flush();
-    }
-
-    // TODO: move to UsageStatsProtoV2
-    static void readPendingEvents(InputStream in, List<UsageEvents.Event> events)
-            throws IOException {
-        final ProtoInputStream proto = new ProtoInputStream(in);
-        final List<String> stringPool = new ArrayList<>();
-        final IntervalStats tmpStatsObj = new IntervalStats();
-        while (true) {
-            switch (proto.nextField()) {
-                case (int) IntervalStatsProto.PENDING_EVENTS:
-                    loadEvent(proto, IntervalStatsProto.PENDING_EVENTS, tmpStatsObj, stringPool);
-                    break;
-                case ProtoInputStream.NO_MORE_FIELDS:
-                    final int eventCount = tmpStatsObj.events.size();
-                    for (int i = 0; i < eventCount; i++) {
-                        events.add(tmpStatsObj.events.get(i));
-                    }
-                    return;
+            try {
+                writeEvent(proto, IntervalStatsProto.EVENT_LOG, stats, stats.events.get(i));
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Unable to write some events to proto.", e);
             }
         }
-    }
 
-    // TODO: move to UsageStatsProtoV2
-    static void writePendingEvents(OutputStream out, List<UsageEvents.Event> events)
-            throws IOException {
-        final ProtoOutputStream proto = new ProtoOutputStream(out);
-        final IntervalStats tmpStatsObj = new IntervalStats();
-        final int eventCount = events.size();
-        for (int i = 0; i < eventCount; i++) {
-            writeEvent(proto, IntervalStatsProto.PENDING_EVENTS, tmpStatsObj, events.get(i));
-        }
         proto.flush();
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
new file mode 100644
index 0000000..7d8e430
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
@@ -0,0 +1,788 @@
+/*
+ * 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.usage;
+
+import android.app.usage.ConfigurationStats;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
+import android.content.res.Configuration;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+/**
+ * UsageStats reader/writer V2 for Protocol Buffer format.
+ */
+final class UsageStatsProtoV2 {
+    private static final String TAG = "UsageStatsProtoV2";
+
+    // Static-only utility class.
+    private UsageStatsProtoV2() {}
+
+    private static UsageStats parseUsageStats(ProtoInputStream proto, final long beginTime)
+            throws IOException {
+        UsageStats stats = new UsageStats();
+        // Time attributes stored is an offset of the beginTime.
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) UsageStatsObfuscatedProto.PACKAGE_TOKEN:
+                    stats.mPackageToken = proto.readInt(
+                            UsageStatsObfuscatedProto.PACKAGE_TOKEN) - 1;
+                    break;
+                case (int) UsageStatsObfuscatedProto.LAST_TIME_ACTIVE_MS:
+                    stats.mLastTimeUsed = beginTime + proto.readLong(
+                            UsageStatsObfuscatedProto.LAST_TIME_ACTIVE_MS);
+                    break;
+                case (int) UsageStatsObfuscatedProto.TOTAL_TIME_ACTIVE_MS:
+                    stats.mTotalTimeInForeground = proto.readLong(
+                            UsageStatsObfuscatedProto.TOTAL_TIME_ACTIVE_MS);
+                    break;
+                case (int) UsageStatsObfuscatedProto.APP_LAUNCH_COUNT:
+                    stats.mAppLaunchCount = proto.readInt(
+                            UsageStatsObfuscatedProto.APP_LAUNCH_COUNT);
+                    break;
+                case (int) UsageStatsObfuscatedProto.CHOOSER_ACTIONS:
+                    try {
+                        final long token = proto.start(UsageStatsObfuscatedProto.CHOOSER_ACTIONS);
+                        loadChooserCounts(proto, stats);
+                        proto.end(token);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read chooser counts for " + stats.mPackageToken);
+                    }
+                    break;
+                case (int) UsageStatsObfuscatedProto.LAST_TIME_SERVICE_USED_MS:
+                    stats.mLastTimeForegroundServiceUsed = beginTime + proto.readLong(
+                            UsageStatsObfuscatedProto.LAST_TIME_SERVICE_USED_MS);
+                    break;
+                case (int) UsageStatsObfuscatedProto.TOTAL_TIME_SERVICE_USED_MS:
+                    stats.mTotalTimeForegroundServiceUsed = proto.readLong(
+                            UsageStatsObfuscatedProto.TOTAL_TIME_SERVICE_USED_MS);
+                    break;
+                case (int) UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS:
+                    stats.mLastTimeVisible = beginTime + proto.readLong(
+                            UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS);
+                    break;
+                case (int) UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS:
+                    stats.mTotalTimeVisible = proto.readLong(
+                            UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    // mLastTimeUsed was not read, assume default value of 0 plus beginTime
+                    if (stats.mLastTimeUsed == 0) {
+                        stats.mLastTimeUsed = beginTime;
+                    }
+                    return stats;
+            }
+        }
+    }
+
+    private static void loadCountAndTime(ProtoInputStream proto, long fieldId,
+            IntervalStats.EventTracker tracker) {
+        try {
+            final long token = proto.start(fieldId);
+            while (true) {
+                switch (proto.nextField()) {
+                    case (int) IntervalStatsObfuscatedProto.CountAndTime.COUNT:
+                        tracker.count = proto.readInt(
+                                IntervalStatsObfuscatedProto.CountAndTime.COUNT);
+                        break;
+                    case (int) IntervalStatsObfuscatedProto.CountAndTime.TIME_MS:
+                        tracker.duration = proto.readLong(
+                                IntervalStatsObfuscatedProto.CountAndTime.TIME_MS);
+                        break;
+                    case ProtoInputStream.NO_MORE_FIELDS:
+                        proto.end(token);
+                        return;
+                }
+            }
+        } catch (IOException e) {
+            Slog.e(TAG, "Unable to read event tracker " + fieldId, e);
+        }
+    }
+
+    private static void loadChooserCounts(ProtoInputStream proto, UsageStats usageStats)
+            throws IOException {
+        int actionToken;
+        SparseIntArray counts;
+        if (proto.nextField(UsageStatsObfuscatedProto.ChooserAction.ACTION_TOKEN)) {
+            // Fast path; this should work for most cases since the action token is written first
+            actionToken = proto.readInt(UsageStatsObfuscatedProto.ChooserAction.ACTION_TOKEN) - 1;
+            counts = usageStats.mChooserCountsObfuscated.get(actionToken);
+            if (counts == null) {
+                counts = new SparseIntArray();
+                usageStats.mChooserCountsObfuscated.put(actionToken, counts);
+            }
+        } else {
+            counts = new SparseIntArray();
+        }
+
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) UsageStatsObfuscatedProto.ChooserAction.ACTION_TOKEN:
+                    // Fast path failed for some reason, add the SparseIntArray object to usageStats
+                    actionToken = proto.readInt(
+                            UsageStatsObfuscatedProto.ChooserAction.ACTION_TOKEN) - 1;
+                    usageStats.mChooserCountsObfuscated.put(actionToken, counts);
+                    break;
+                case (int) UsageStatsObfuscatedProto.ChooserAction.COUNTS:
+                    final long token = proto.start(UsageStatsObfuscatedProto.ChooserAction.COUNTS);
+                    loadCountsForAction(proto, counts);
+                    proto.end(token);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    return; // if the action was never read, the loaded counts will be ignored.
+            }
+        }
+    }
+
+    private static void loadCountsForAction(ProtoInputStream proto, SparseIntArray counts)
+            throws IOException {
+        int categoryToken = PackagesTokenData.UNASSIGNED_TOKEN;
+        int count = 0;
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) UsageStatsObfuscatedProto.ChooserAction.CategoryCount.CATEGORY_TOKEN:
+                    categoryToken = proto.readInt(
+                            UsageStatsObfuscatedProto.ChooserAction.CategoryCount.CATEGORY_TOKEN)
+                            - 1;
+                    break;
+                case (int) UsageStatsObfuscatedProto.ChooserAction.CategoryCount.COUNT:
+                    count = proto.readInt(
+                            UsageStatsObfuscatedProto.ChooserAction.CategoryCount.COUNT);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    if (categoryToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                        counts.put(categoryToken, count);
+                    }
+                    return;
+            }
+        }
+    }
+
+    private static void loadConfigStats(ProtoInputStream proto, IntervalStats stats)
+            throws IOException {
+        boolean configActive = false;
+        final Configuration config = new Configuration();
+        ConfigurationStats configStats = new ConfigurationStats();
+        if (proto.nextField(IntervalStatsObfuscatedProto.Configuration.CONFIG)) {
+            // Fast path; this should work since the configuration is written first
+            config.readFromProto(proto, IntervalStatsObfuscatedProto.Configuration.CONFIG);
+            configStats = stats.getOrCreateConfigurationStats(config);
+        }
+
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsObfuscatedProto.Configuration.CONFIG:
+                    // Fast path failed from some reason, add ConfigStats object to statsOut now
+                    config.readFromProto(proto, IntervalStatsObfuscatedProto.Configuration.CONFIG);
+                    final ConfigurationStats temp = stats.getOrCreateConfigurationStats(config);
+                    temp.mLastTimeActive = configStats.mLastTimeActive;
+                    temp.mTotalTimeActive = configStats.mTotalTimeActive;
+                    temp.mActivationCount = configStats.mActivationCount;
+                    configStats = temp;
+                    break;
+                case (int) IntervalStatsObfuscatedProto.Configuration.LAST_TIME_ACTIVE_MS:
+                    configStats.mLastTimeActive = stats.beginTime + proto.readLong(
+                            IntervalStatsObfuscatedProto.Configuration.LAST_TIME_ACTIVE_MS);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.Configuration.TOTAL_TIME_ACTIVE_MS:
+                    configStats.mTotalTimeActive = proto.readLong(
+                            IntervalStatsObfuscatedProto.Configuration.TOTAL_TIME_ACTIVE_MS);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.Configuration.COUNT:
+                    configStats.mActivationCount = proto.readInt(
+                            IntervalStatsObfuscatedProto.Configuration.COUNT);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.Configuration.ACTIVE:
+                    configActive = proto.readBoolean(
+                            IntervalStatsObfuscatedProto.Configuration.ACTIVE);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    // mLastTimeActive was not assigned, assume default value of 0 plus beginTime
+                    if (configStats.mLastTimeActive == 0) {
+                        configStats.mLastTimeActive = stats.beginTime;
+                    }
+                    if (configActive) {
+                        stats.activeConfiguration = configStats.mConfiguration;
+                    }
+                    return;
+            }
+        }
+    }
+
+    private static UsageEvents.Event parseEvent(ProtoInputStream proto, long beginTime)
+            throws IOException {
+        final UsageEvents.Event event = new UsageEvents.Event();
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) EventObfuscatedProto.PACKAGE_TOKEN:
+                    event.mPackageToken = proto.readInt(EventObfuscatedProto.PACKAGE_TOKEN) - 1;
+                    break;
+                case (int) EventObfuscatedProto.CLASS_TOKEN:
+                    event.mClassToken = proto.readInt(EventObfuscatedProto.CLASS_TOKEN) - 1;
+                    break;
+                case (int) EventObfuscatedProto.TIME_MS:
+                    event.mTimeStamp = beginTime + proto.readLong(EventObfuscatedProto.TIME_MS);
+                    break;
+                case (int) EventObfuscatedProto.FLAGS:
+                    event.mFlags = proto.readInt(EventObfuscatedProto.FLAGS);
+                    break;
+                case (int) EventObfuscatedProto.TYPE:
+                    event.mEventType = proto.readInt(EventObfuscatedProto.TYPE);
+                    break;
+                case (int) EventObfuscatedProto.CONFIG:
+                    event.mConfiguration = new Configuration();
+                    event.mConfiguration.readFromProto(proto, EventObfuscatedProto.CONFIG);
+                    break;
+                case (int) EventObfuscatedProto.SHORTCUT_ID_TOKEN:
+                    event.mShortcutIdToken = proto.readInt(
+                            EventObfuscatedProto.SHORTCUT_ID_TOKEN) - 1;
+                    break;
+                case (int) EventObfuscatedProto.STANDBY_BUCKET:
+                    event.mBucketAndReason = proto.readInt(EventObfuscatedProto.STANDBY_BUCKET);
+                    break;
+                case (int) EventObfuscatedProto.NOTIFICATION_CHANNEL_ID_TOKEN:
+                    event.mNotificationChannelIdToken = proto.readInt(
+                            EventObfuscatedProto.NOTIFICATION_CHANNEL_ID_TOKEN) - 1;
+                    break;
+                case (int) EventObfuscatedProto.INSTANCE_ID:
+                    event.mInstanceId = proto.readInt(EventObfuscatedProto.INSTANCE_ID);
+                    break;
+                case (int) EventObfuscatedProto.TASK_ROOT_PACKAGE_TOKEN:
+                    event.mTaskRootPackageToken = proto.readInt(
+                            EventObfuscatedProto.TASK_ROOT_PACKAGE_TOKEN) - 1;
+                    break;
+                case (int) EventObfuscatedProto.TASK_ROOT_CLASS_TOKEN:
+                    event.mTaskRootClassToken = proto.readInt(
+                            EventObfuscatedProto.TASK_ROOT_CLASS_TOKEN) - 1;
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    // timeStamp was not read, assume default value 0 plus beginTime
+                    if (event.mTimeStamp == 0) {
+                        event.mTimeStamp = beginTime;
+                    }
+                    return event.mPackageToken == PackagesTokenData.UNASSIGNED_TOKEN ? null : event;
+            }
+        }
+    }
+
+    private static void writeUsageStats(ProtoOutputStream proto, final long beginTime,
+            final UsageStats stats) throws IllegalArgumentException {
+        // Time attributes stored as an offset of the beginTime.
+        proto.write(UsageStatsObfuscatedProto.PACKAGE_TOKEN, stats.mPackageToken + 1);
+        proto.write(UsageStatsObfuscatedProto.LAST_TIME_ACTIVE_MS, stats.mLastTimeUsed - beginTime);
+        proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_ACTIVE_MS, stats.mTotalTimeInForeground);
+        proto.write(UsageStatsObfuscatedProto.LAST_TIME_SERVICE_USED_MS,
+                stats.mLastTimeForegroundServiceUsed - beginTime);
+        proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_SERVICE_USED_MS,
+                stats.mTotalTimeForegroundServiceUsed);
+        proto.write(UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS,
+                stats.mLastTimeVisible - beginTime);
+        proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS, stats.mTotalTimeVisible);
+        proto.write(UsageStatsObfuscatedProto.APP_LAUNCH_COUNT, stats.mAppLaunchCount);
+        try {
+            writeChooserCounts(proto, stats);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Unable to write chooser counts for " + stats.mPackageName, e);
+        }
+    }
+
+    private static void writeCountAndTime(ProtoOutputStream proto, long fieldId, int count,
+            long time) throws IllegalArgumentException {
+        final long token = proto.start(fieldId);
+        proto.write(IntervalStatsObfuscatedProto.CountAndTime.COUNT, count);
+        proto.write(IntervalStatsObfuscatedProto.CountAndTime.TIME_MS, time);
+        proto.end(token);
+    }
+
+    private static void writeChooserCounts(ProtoOutputStream proto, final UsageStats stats)
+            throws IllegalArgumentException {
+        if (stats == null || stats.mChooserCountsObfuscated.size() == 0) {
+            return;
+        }
+        final int chooserCountSize = stats.mChooserCountsObfuscated.size();
+        for (int i = 0; i < chooserCountSize; i++) {
+            final int action = stats.mChooserCountsObfuscated.keyAt(i);
+            final SparseIntArray counts = stats.mChooserCountsObfuscated.valueAt(i);
+            if (counts == null || counts.size() == 0) {
+                continue;
+            }
+            final long token = proto.start(UsageStatsObfuscatedProto.CHOOSER_ACTIONS);
+            proto.write(UsageStatsObfuscatedProto.ChooserAction.ACTION_TOKEN, action + 1);
+            writeCountsForAction(proto, counts);
+            proto.end(token);
+        }
+    }
+
+    private static void writeCountsForAction(ProtoOutputStream proto, SparseIntArray counts)
+            throws IllegalArgumentException {
+        final int countsSize = counts.size();
+        for (int i = 0; i < countsSize; i++) {
+            final int category = counts.keyAt(i);
+            final int count = counts.valueAt(i);
+            if (count <= 0) {
+                continue;
+            }
+            final long token = proto.start(UsageStatsObfuscatedProto.ChooserAction.COUNTS);
+            proto.write(UsageStatsObfuscatedProto.ChooserAction.CategoryCount.CATEGORY_TOKEN,
+                    category + 1);
+            proto.write(UsageStatsObfuscatedProto.ChooserAction.CategoryCount.COUNT, count);
+            proto.end(token);
+        }
+    }
+
+    private static void writeConfigStats(ProtoOutputStream proto, final long statsBeginTime,
+            final ConfigurationStats configStats, boolean isActive)
+            throws IllegalArgumentException {
+        configStats.mConfiguration.writeToProto(proto,
+                IntervalStatsObfuscatedProto.Configuration.CONFIG);
+        proto.write(IntervalStatsObfuscatedProto.Configuration.LAST_TIME_ACTIVE_MS,
+                configStats.mLastTimeActive - statsBeginTime);
+        proto.write(IntervalStatsObfuscatedProto.Configuration.TOTAL_TIME_ACTIVE_MS,
+                configStats.mTotalTimeActive);
+        proto.write(IntervalStatsObfuscatedProto.Configuration.COUNT, configStats.mActivationCount);
+        proto.write(IntervalStatsObfuscatedProto.Configuration.ACTIVE, isActive);
+    }
+
+    private static void writeEvent(ProtoOutputStream proto, final long statsBeginTime,
+            final UsageEvents.Event event) throws IllegalArgumentException {
+        proto.write(EventObfuscatedProto.PACKAGE_TOKEN, event.mPackageToken + 1);
+        if (event.mClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+            proto.write(EventObfuscatedProto.CLASS_TOKEN, event.mClassToken + 1);
+        }
+        proto.write(EventObfuscatedProto.TIME_MS, event.mTimeStamp - statsBeginTime);
+        proto.write(EventObfuscatedProto.FLAGS, event.mFlags);
+        proto.write(EventObfuscatedProto.TYPE, event.mEventType);
+        proto.write(EventObfuscatedProto.INSTANCE_ID, event.mInstanceId);
+        if (event.mTaskRootPackageToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+            proto.write(EventObfuscatedProto.TASK_ROOT_PACKAGE_TOKEN,
+                    event.mTaskRootPackageToken + 1);
+        }
+        if (event.mTaskRootClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+            proto.write(EventObfuscatedProto.TASK_ROOT_CLASS_TOKEN, event.mTaskRootClassToken + 1);
+        }
+        switch (event.mEventType) {
+            case UsageEvents.Event.CONFIGURATION_CHANGE:
+                if (event.mConfiguration != null) {
+                    event.mConfiguration.writeToProto(proto, EventObfuscatedProto.CONFIG);
+                }
+                break;
+            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                if (event.mBucketAndReason != 0) {
+                    proto.write(EventObfuscatedProto.STANDBY_BUCKET, event.mBucketAndReason);
+                }
+                break;
+            case UsageEvents.Event.SHORTCUT_INVOCATION:
+                if (event.mShortcutIdToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                    proto.write(EventObfuscatedProto.SHORTCUT_ID_TOKEN, event.mShortcutIdToken + 1);
+                }
+                break;
+            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                if (event.mNotificationChannelIdToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                    proto.write(EventObfuscatedProto.NOTIFICATION_CHANNEL_ID_TOKEN,
+                            event.mNotificationChannelIdToken + 1);
+                }
+                break;
+        }
+    }
+
+    /**
+     * Populates a tokenized version of interval stats from the input stream given.
+     *
+     * @param in the input stream from which to read events.
+     * @param stats the interval stats object which will be populated.
+     */
+    public static void read(InputStream in, IntervalStats stats) throws IOException {
+        final ProtoInputStream proto = new ProtoInputStream(in);
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsObfuscatedProto.END_TIME_MS:
+                    stats.endTime = stats.beginTime + proto.readLong(
+                            IntervalStatsObfuscatedProto.END_TIME_MS);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.MAJOR_VERSION:
+                    stats.majorVersion = proto.readInt(IntervalStatsObfuscatedProto.MAJOR_VERSION);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.MINOR_VERSION:
+                    stats.minorVersion = proto.readInt(IntervalStatsObfuscatedProto.MINOR_VERSION);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.INTERACTIVE:
+                    loadCountAndTime(proto, IntervalStatsObfuscatedProto.INTERACTIVE,
+                            stats.interactiveTracker);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.NON_INTERACTIVE:
+                    loadCountAndTime(proto, IntervalStatsObfuscatedProto.NON_INTERACTIVE,
+                            stats.nonInteractiveTracker);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.KEYGUARD_SHOWN:
+                    loadCountAndTime(proto, IntervalStatsObfuscatedProto.KEYGUARD_SHOWN,
+                            stats.keyguardShownTracker);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.KEYGUARD_HIDDEN:
+                    loadCountAndTime(proto, IntervalStatsObfuscatedProto.KEYGUARD_HIDDEN,
+                            stats.keyguardHiddenTracker);
+                    break;
+                case (int) IntervalStatsObfuscatedProto.PACKAGES:
+                    try {
+                        final long packagesToken = proto.start(
+                                IntervalStatsObfuscatedProto.PACKAGES);
+                        UsageStats usageStats = parseUsageStats(proto, stats.beginTime);
+                        if (usageStats.mPackageToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+                            stats.packageStatsObfuscated.put(usageStats.mPackageToken, usageStats);
+                        }
+                        proto.end(packagesToken);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read some usage stats from proto.", e);
+                    }
+                    break;
+                case (int) IntervalStatsObfuscatedProto.CONFIGURATIONS:
+                    try {
+                        final long configsToken = proto.start(
+                                IntervalStatsObfuscatedProto.CONFIGURATIONS);
+                        loadConfigStats(proto, stats);
+                        proto.end(configsToken);
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read some configuration stats from proto.", e);
+                    }
+                    break;
+                case (int) IntervalStatsObfuscatedProto.EVENT_LOG:
+                    try {
+                        final long eventsToken = proto.start(
+                                IntervalStatsObfuscatedProto.EVENT_LOG);
+                        UsageEvents.Event event = parseEvent(proto, stats.beginTime);
+                        proto.end(eventsToken);
+                        if (event != null) {
+                            stats.events.insert(event);
+                        }
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to read some events from proto.", e);
+                    }
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    // endTime not assigned, assume default value of 0 plus beginTime
+                    if (stats.endTime == 0) {
+                        stats.endTime = stats.beginTime;
+                    }
+                    return;
+            }
+        }
+    }
+
+    /**
+     * Writes the tokenized interval stats object to a ProtoBuf file.
+     *
+     * @param out the output stream to which to write the interval stats data.
+     * @param stats the interval stats object to write to the proto file.
+     */
+    public static void write(OutputStream out, IntervalStats stats)
+            throws IOException, IllegalArgumentException {
+        final ProtoOutputStream proto = new ProtoOutputStream(out);
+        proto.write(IntervalStatsObfuscatedProto.END_TIME_MS, stats.endTime - stats.beginTime);
+        proto.write(IntervalStatsObfuscatedProto.MAJOR_VERSION, stats.majorVersion);
+        proto.write(IntervalStatsObfuscatedProto.MINOR_VERSION, stats.minorVersion);
+
+        try {
+            writeCountAndTime(proto, IntervalStatsObfuscatedProto.INTERACTIVE,
+                    stats.interactiveTracker.count, stats.interactiveTracker.duration);
+            writeCountAndTime(proto, IntervalStatsObfuscatedProto.NON_INTERACTIVE,
+                    stats.nonInteractiveTracker.count, stats.nonInteractiveTracker.duration);
+            writeCountAndTime(proto, IntervalStatsObfuscatedProto.KEYGUARD_SHOWN,
+                    stats.keyguardShownTracker.count, stats.keyguardShownTracker.duration);
+            writeCountAndTime(proto, IntervalStatsObfuscatedProto.KEYGUARD_HIDDEN,
+                    stats.keyguardHiddenTracker.count, stats.keyguardHiddenTracker.duration);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Unable to write some interval stats trackers to proto.", e);
+        }
+
+        final int statsCount = stats.packageStatsObfuscated.size();
+        for (int i = 0; i < statsCount; i++) {
+            try {
+                final long token = proto.start(IntervalStatsObfuscatedProto.PACKAGES);
+                writeUsageStats(proto, stats.beginTime, stats.packageStatsObfuscated.valueAt(i));
+                proto.end(token);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Unable to write some usage stats to proto.", e);
+            }
+        }
+        final int configCount = stats.configurations.size();
+        for (int i = 0; i < configCount; i++) {
+            boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i));
+            try {
+                final long token = proto.start(IntervalStatsObfuscatedProto.CONFIGURATIONS);
+                writeConfigStats(proto, stats.beginTime, stats.configurations.valueAt(i), active);
+                proto.end(token);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Unable to write some configuration stats to proto.", e);
+            }
+        }
+        final int eventCount = stats.events.size();
+        for (int i = 0; i < eventCount; i++) {
+            try {
+                final long token = proto.start(IntervalStatsObfuscatedProto.EVENT_LOG);
+                writeEvent(proto, stats.beginTime, stats.events.get(i));
+                proto.end(token);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Unable to write some events to proto.", e);
+            }
+        }
+
+        proto.flush();
+    }
+
+    /***** Read/Write obfuscated packages data logic. *****/
+
+    private static void loadPackagesMap(ProtoInputStream proto,
+            SparseArray<ArrayList<String>> tokensToPackagesMap) throws IOException {
+        int key = PackagesTokenData.UNASSIGNED_TOKEN;
+        final ArrayList<String> strings = new ArrayList<>();
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) ObfuscatedPackagesProto.PackagesMap.PACKAGE_TOKEN:
+                    key = proto.readInt(ObfuscatedPackagesProto.PackagesMap.PACKAGE_TOKEN) - 1;
+                    break;
+                case (int) ObfuscatedPackagesProto.PackagesMap.STRINGS:
+                    strings.add(proto.readString(ObfuscatedPackagesProto.PackagesMap.STRINGS));
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    if (key != PackagesTokenData.UNASSIGNED_TOKEN) {
+                        tokensToPackagesMap.put(key, strings);
+                    }
+                    return;
+            }
+        }
+    }
+
+    /**
+     * Populates the package mappings from the input stream given.
+     *
+     * @param in the input stream from which to read the mappings.
+     * @param packagesTokenData the packages data object to which the data will be read to.
+     */
+    static void readObfuscatedData(InputStream in, PackagesTokenData packagesTokenData)
+            throws IOException {
+        final ProtoInputStream proto = new ProtoInputStream(in);
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) ObfuscatedPackagesProto.COUNTER:
+                    packagesTokenData.counter = proto.readInt(ObfuscatedPackagesProto.COUNTER);
+                    break;
+                case (int) ObfuscatedPackagesProto.PACKAGES_MAP:
+                    final long token = proto.start(ObfuscatedPackagesProto.PACKAGES_MAP);
+                    loadPackagesMap(proto, packagesTokenData.tokensToPackagesMap);
+                    proto.end(token);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    return;
+            }
+        }
+    }
+
+    /**
+     * Writes the packages mapping data to a ProtoBuf file.
+     *
+     * @param out the output stream to which to write the mappings.
+     * @param packagesTokenData the packages data object holding the data to write.
+     */
+    static void writeObfuscatedData(OutputStream out, PackagesTokenData packagesTokenData)
+            throws IOException, IllegalArgumentException {
+        final ProtoOutputStream proto = new ProtoOutputStream(out);
+        proto.write(ObfuscatedPackagesProto.COUNTER, packagesTokenData.counter);
+
+        final int mapSize = packagesTokenData.tokensToPackagesMap.size();
+        for (int i = 0; i < mapSize; i++) {
+            final long token = proto.start(ObfuscatedPackagesProto.PACKAGES_MAP);
+            int packageToken = packagesTokenData.tokensToPackagesMap.keyAt(i);
+            proto.write(ObfuscatedPackagesProto.PackagesMap.PACKAGE_TOKEN, packageToken + 1);
+
+            final ArrayList<String> strings = packagesTokenData.tokensToPackagesMap.valueAt(i);
+            final int listSize = strings.size();
+            for (int j = 0; j < listSize; j++) {
+                proto.write(ObfuscatedPackagesProto.PackagesMap.STRINGS, strings.get(j));
+            }
+            proto.end(token);
+        }
+
+        proto.flush();
+    }
+
+    /***** Read/Write pending events logic. *****/
+
+    private static UsageEvents.Event parsePendingEvent(ProtoInputStream proto) throws IOException {
+        final UsageEvents.Event event = new UsageEvents.Event();
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) PendingEventProto.PACKAGE_NAME:
+                    event.mPackage = proto.readString(PendingEventProto.PACKAGE_NAME);
+                    break;
+                case (int) PendingEventProto.CLASS_NAME:
+                    event.mClass = proto.readString(PendingEventProto.CLASS_NAME);
+                    break;
+                case (int) PendingEventProto.TIME_MS:
+                    event.mTimeStamp = proto.readLong(PendingEventProto.TIME_MS);
+                    break;
+                case (int) PendingEventProto.FLAGS:
+                    event.mFlags = proto.readInt(PendingEventProto.FLAGS);
+                    break;
+                case (int) PendingEventProto.TYPE:
+                    event.mEventType = proto.readInt(PendingEventProto.TYPE);
+                    break;
+                case (int) PendingEventProto.CONFIG:
+                    event.mConfiguration = new Configuration();
+                    event.mConfiguration.readFromProto(proto, PendingEventProto.CONFIG);
+                    break;
+                case (int) PendingEventProto.SHORTCUT_ID:
+                    event.mShortcutId = proto.readString(PendingEventProto.SHORTCUT_ID);
+                    break;
+                case (int) PendingEventProto.STANDBY_BUCKET:
+                    event.mBucketAndReason = proto.readInt(PendingEventProto.STANDBY_BUCKET);
+                    break;
+                case (int) PendingEventProto.NOTIFICATION_CHANNEL_ID:
+                    event.mNotificationChannelId = proto.readString(
+                            PendingEventProto.NOTIFICATION_CHANNEL_ID);
+                    break;
+                case (int) PendingEventProto.INSTANCE_ID:
+                    event.mInstanceId = proto.readInt(PendingEventProto.INSTANCE_ID);
+                    break;
+                case (int) PendingEventProto.TASK_ROOT_PACKAGE:
+                    event.mTaskRootPackage = proto.readString(PendingEventProto.TASK_ROOT_PACKAGE);
+                    break;
+                case (int) PendingEventProto.TASK_ROOT_CLASS:
+                    event.mTaskRootClass = proto.readString(PendingEventProto.TASK_ROOT_CLASS);
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    // Handle default values for certain events types
+                    switch (event.mEventType) {
+                        case UsageEvents.Event.CONFIGURATION_CHANGE:
+                            if (event.mConfiguration == null) {
+                                event.mConfiguration = new Configuration();
+                            }
+                            break;
+                        case UsageEvents.Event.SHORTCUT_INVOCATION:
+                            if (event.mShortcutId == null) {
+                                event.mShortcutId = "";
+                            }
+                            break;
+                        case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                            if (event.mNotificationChannelId == null) {
+                                event.mNotificationChannelId = "";
+                            }
+                            break;
+                    }
+                    return event.mPackage == null ? null : event;
+            }
+        }
+    }
+
+    /**
+     * Populates the list of pending events from the input stream given.
+     *
+     * @param in the input stream from which to read the pending events.
+     * @param events the list of pending events to populate.
+     */
+    static void readPendingEvents(InputStream in, LinkedList<UsageEvents.Event> events)
+            throws IOException {
+        final ProtoInputStream proto = new ProtoInputStream(in);
+        while (true) {
+            switch (proto.nextField()) {
+                case (int) IntervalStatsObfuscatedProto.PENDING_EVENTS:
+                    try {
+                        final long token = proto.start(IntervalStatsObfuscatedProto.PENDING_EVENTS);
+                        UsageEvents.Event event = parsePendingEvent(proto);
+                        proto.end(token);
+                        if (event != null) {
+                            events.add(event);
+                        }
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Unable to parse some pending events from proto.", e);
+                    }
+                    break;
+                case ProtoInputStream.NO_MORE_FIELDS:
+                    return;
+            }
+        }
+    }
+
+    private static void writePendingEvent(ProtoOutputStream proto, UsageEvents.Event event)
+            throws IllegalArgumentException {
+        proto.write(PendingEventProto.PACKAGE_NAME, event.mPackage);
+        if (event.mClass != null) {
+            proto.write(PendingEventProto.CLASS_NAME, event.mClass);
+        }
+        proto.write(PendingEventProto.TIME_MS, event.mTimeStamp);
+        proto.write(PendingEventProto.FLAGS, event.mFlags);
+        proto.write(PendingEventProto.TYPE, event.mEventType);
+        proto.write(PendingEventProto.INSTANCE_ID, event.mInstanceId);
+        if (event.mTaskRootPackage != null) {
+            proto.write(PendingEventProto.TASK_ROOT_PACKAGE, event.mTaskRootPackage);
+        }
+        if (event.mTaskRootClass != null) {
+            proto.write(PendingEventProto.TASK_ROOT_CLASS, event.mTaskRootClass);
+        }
+        switch (event.mEventType) {
+            case UsageEvents.Event.CONFIGURATION_CHANGE:
+                if (event.mConfiguration != null) {
+                    event.mConfiguration.writeToProto(proto, PendingEventProto.CONFIG);
+                }
+                break;
+            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                if (event.mBucketAndReason != 0) {
+                    proto.write(PendingEventProto.STANDBY_BUCKET, event.mBucketAndReason);
+                }
+                break;
+            case UsageEvents.Event.SHORTCUT_INVOCATION:
+                if (event.mShortcutId != null) {
+                    proto.write(PendingEventProto.SHORTCUT_ID, event.mShortcutId);
+                }
+                break;
+            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                if (event.mNotificationChannelId != null) {
+                    proto.write(PendingEventProto.NOTIFICATION_CHANNEL_ID,
+                            event.mNotificationChannelId);
+                }
+                break;
+        }
+    }
+
+    /**
+     * Writes the pending events to a ProtoBuf file.
+     *
+     * @param out the output stream to which to write the pending events.
+     * @param events the list of pending events.
+     */
+    static void writePendingEvents(OutputStream out, LinkedList<UsageEvents.Event> events)
+            throws IOException, IllegalArgumentException {
+        final ProtoOutputStream proto = new ProtoOutputStream(out);
+        final int eventCount = events.size();
+        for (int i = 0; i < eventCount; i++) {
+            try {
+                final long token = proto.start(IntervalStatsObfuscatedProto.PENDING_EVENTS);
+                writePendingEvent(proto, events.get(i));
+                proto.end(token);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Unable to write some pending events to proto.", e);
+            }
+        }
+        proto.flush();
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index ecee709..6a80568 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -86,6 +86,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -97,8 +98,6 @@
 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;
@@ -143,6 +142,7 @@
     static final int MSG_UID_STATE_CHANGED = 3;
     static final int MSG_REPORT_EVENT_TO_ALL_USERID = 4;
     static final int MSG_UNLOCKED_USER = 5;
+    static final int MSG_PACKAGE_REMOVED = 6;
 
     private final Object mLock = new Object();
     Handler mHandler;
@@ -150,7 +150,6 @@
     UserManager mUserManager;
     PackageManager mPackageManager;
     PackageManagerInternal mPackageManagerInternal;
-    PackageMonitor mPackageMonitor;
     IDeviceIdleController mDeviceIdleController;
     // Do not use directly. Call getDpmInternal() instead
     DevicePolicyManagerInternal mDpmInternal;
@@ -166,6 +165,8 @@
     /** Manages app time limit observers */
     AppTimeLimitController mAppTimeLimit;
 
+    private final PackageMonitor mPackageMonitor = new MyPackageMonitor();
+
     // A map maintaining a queue of events to be reported per user.
     private final SparseArray<LinkedList<Event>> mReportedEvents = new SparseArray<>();
     final SparseArray<ArraySet<String>> mUsageReporters = new SparseArray();
@@ -180,8 +181,8 @@
         }
     }
 
-    private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener =
-            new UsageStatsManagerInternal.AppIdleStateChangeListener() {
+    private AppIdleStateChangeListener mStandbyChangeListener =
+            new AppIdleStateChangeListener() {
                 @Override
                 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
                         int bucket, int reason) {
@@ -191,11 +192,6 @@
                     event.mPackage = packageName;
                     reportEventOrAddToQueue(userId, event);
                 }
-
-                @Override
-                public void onParoleStateChanged(boolean isParoleOn) {
-
-                }
             };
 
     public UsageStatsService(Context context) {
@@ -250,12 +246,15 @@
 
         mAppStandby.addListener(mStandbyChangeListener);
 
+        mPackageMonitor.register(getContext(), null, UserHandle.ALL, true);
+
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_STARTED);
         getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
                 null, mHandler);
 
         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
+        publishLocalService(AppStandbyInternal.class, mAppStandby);
         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
     }
 
@@ -624,7 +623,7 @@
             final AtomicFile af = new AtomicFile(pendingEventsFiles[i]);
             try {
                 try (FileInputStream in = af.openRead()) {
-                    UsageStatsProto.readPendingEvents(in, pendingEvents);
+                    UsageStatsProtoV2.readPendingEvents(in, pendingEvents);
                 }
             } catch (IOException e) {
                 // Even if one file read fails, exit here to keep all events in order on disk -
@@ -654,11 +653,11 @@
         FileOutputStream fos = null;
         try {
             fos = af.startWrite();
-            UsageStatsProto.writePendingEvents(fos, pendingEvents);
+            UsageStatsProtoV2.writePendingEvents(fos, pendingEvents);
             af.finishWrite(fos);
             fos = null;
             pendingEvents.clear();
-        } catch (IOException e) {
+        } catch (IOException | IllegalArgumentException e) {
             Slog.e(TAG, "Failed to write " + pendingEventsFile.getAbsolutePath()
                     + " for user " + userId);
         } finally {
@@ -850,6 +849,26 @@
     }
 
     /**
+     * Called by the Handler for message MSG_PACKAGE_REMOVED.
+     */
+    private void onPackageRemoved(int userId, String packageName) {
+        synchronized (mLock) {
+            final long timeRemoved = System.currentTimeMillis();
+            if (!mUserUnlockedStates.get(userId, false)) {
+                // If user is not unlocked and a package is removed for them, we will handle it
+                // when the user service is initialized and package manager is queried.
+                return;
+            }
+            final UserUsageStatsService userService = mUserState.get(userId);
+            if (userService == null) {
+                return;
+            }
+
+            userService.onPackageRemoved(packageName, timeRemoved);
+        }
+    }
+
+    /**
      * Called by the Binder stub.
      */
     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
@@ -1037,21 +1056,13 @@
                                 ipw.decreaseIndent();
                             }
                         } else {
-                            final int user;
-                            try {
-                                user = Integer.valueOf(args[i + 1]);
-                            } catch (NumberFormatException nfe) {
-                                ipw.println("invalid user specified.");
-                                return;
+                            final int user = parseUserIdFromArgs(args, i, ipw);
+                            if (user != UserHandle.USER_NULL) {
+                                final String[] remainingArgs = Arrays.copyOfRange(
+                                        args, i + 2, args.length);
+                                // dump everything for the specified user
+                                mUserState.get(user).dumpFile(ipw, remainingArgs);
                             }
-                            if (mUserState.indexOfKey(user) < 0) {
-                                ipw.println("the specified user does not exist.");
-                                return;
-                            }
-                            final String[] remainingArgs = Arrays.copyOfRange(
-                                    args, i + 2, args.length);
-                            // dump everything for the specified user
-                            mUserState.get(user).dumpFile(ipw, remainingArgs);
                         }
                         return;
                     } else if ("database-info".equals(arg)) {
@@ -1066,19 +1077,11 @@
                                 ipw.decreaseIndent();
                             }
                         } else {
-                            final int user;
-                            try {
-                                user = Integer.valueOf(args[i + 1]);
-                            } catch (NumberFormatException nfe) {
-                                ipw.println("invalid user specified.");
-                                return;
+                            final int user = parseUserIdFromArgs(args, i, ipw);
+                            if (user != UserHandle.USER_NULL) {
+                                // dump info only for the specified user
+                                mUserState.get(user).dumpDatabaseInfo(ipw);
                             }
-                            if (mUserState.indexOfKey(user) < 0) {
-                                ipw.println("the specified user does not exist.");
-                                return;
-                            }
-                            // dump info only for the specified user
-                            mUserState.get(user).dumpDatabaseInfo(ipw);
                         }
                         return;
                     } else if ("appstandby".equals(arg)) {
@@ -1086,15 +1089,18 @@
                         return;
                     } else if ("stats-directory".equals(arg)) {
                         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
-                        final int userId;
-                        try {
-                            userId = Integer.valueOf(args[i + 1]);
-                        } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
-                            ipw.println("invalid user specified.");
-                            return;
+                        final int userId = parseUserIdFromArgs(args, i, ipw);
+                        if (userId != UserHandle.USER_NULL) {
+                            ipw.println(new File(Environment.getDataSystemCeDirectory(userId),
+                                    "usagestats").getAbsolutePath());
                         }
-                        ipw.println(new File(Environment.getDataSystemCeDirectory(userId),
-                                "usagestats").getAbsolutePath());
+                        return;
+                    } else if ("mappings".equals(arg)) {
+                        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+                        final int userId = parseUserIdFromArgs(args, i, ipw);
+                        if (userId != UserHandle.USER_NULL) {
+                            mUserState.get(userId).dumpMappings(ipw);
+                        }
                         return;
                     } else if (arg != null && !arg.startsWith("-")) {
                         // Anything else that doesn't start with '-' is a pkg to filter
@@ -1133,6 +1139,21 @@
         }
     }
 
+    private int parseUserIdFromArgs(String[] args, int index, IndentingPrintWriter ipw) {
+        final int userId;
+        try {
+            userId = Integer.valueOf(args[index + 1]);
+        } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
+            ipw.println("invalid user specified.");
+            return UserHandle.USER_NULL;
+        }
+        if (mUserState.indexOfKey(userId) < 0) {
+            ipw.println("the specified user does not exist.");
+            return UserHandle.USER_NULL;
+        }
+        return userId;
+    }
+
     class H extends Handler {
         public H(Looper looper) {
             super(looper);
@@ -1164,7 +1185,9 @@
                 case MSG_REMOVE_USER:
                     onUserRemoved(msg.arg1);
                     break;
-
+                case MSG_PACKAGE_REMOVED:
+                    onPackageRemoved(msg.arg1, (String) msg.obj);
+                    break;
                 case MSG_UID_STATE_CHANGED: {
                     final int uid = msg.arg1;
                     final int procState = msg.arg2;
@@ -1426,7 +1449,7 @@
                     Binder.getCallingUid(), userId);
             final long token = Binder.clearCallingIdentity();
             try {
-                return mAppStandby.isAppIdleFilteredOrParoled(
+                return mAppStandby.isAppIdleFiltered(
                         packageName, userId,
                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
             } finally {
@@ -1995,11 +2018,6 @@
         }
 
         @Override
-        public boolean isAppIdleParoleOn() {
-            return mAppStandby.isParoledOrCharging();
-        }
-
-        @Override
         public void prepareShutdown() {
             // This method *WILL* do IO work, but we must block until it is finished or else
             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
@@ -2013,18 +2031,6 @@
         }
 
         @Override
-        public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
-            mAppStandby.addListener(listener);
-            listener.onParoleStateChanged(isAppIdleParoleOn());
-        }
-
-        @Override
-        public void removeAppIdleStateChangeListener(
-                AppIdleStateChangeListener listener) {
-            mAppStandby.removeListener(listener);
-        }
-
-        @Override
         public byte[] getBackupPayload(int user, String key) {
             synchronized (mLock) {
                 if (!mUserUnlockedStates.get(user)) {
@@ -2118,4 +2124,13 @@
             return mAppTimeLimit.getAppUsageLimit(packageName, user);
         }
     }
+
+    private class MyPackageMonitor extends PackageMonitor {
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            mHandler.obtainMessage(MSG_PACKAGE_REMOVED, getChangingUserId(), 0, packageName)
+                    .sendToTarget();
+            super.onPackageRemoved(packageName, uid);
+        }
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 1560b9e..5783932 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -34,7 +34,10 @@
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
 import android.content.res.Configuration;
+import android.os.Process;
 import android.os.SystemClock;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
@@ -44,6 +47,7 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
 import com.android.server.usage.UsageStatsDatabase.StatCombiner;
 
 import java.io.File;
@@ -51,6 +55,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 
 /**
@@ -108,6 +113,7 @@
     }
 
     void init(final long currentTimeMillis) {
+        readPackageMappingsLocked();
         mDatabase.init(currentTimeMillis);
 
         int nullCount = 0;
@@ -140,17 +146,16 @@
         }
 
         // During system reboot, add a DEVICE_SHUTDOWN event to the end of event list, the timestamp
-        // is last time UsageStatsDatabase is persisted to disk.
+        // is last time UsageStatsDatabase is persisted to disk or the last event's time whichever
+        // is higher (because the file system timestamp is round down to integral seconds).
         // Also add a DEVICE_STARTUP event with current system timestamp.
         final IntervalStats currentDailyStats = mCurrentStats[INTERVAL_DAILY];
         if (currentDailyStats != null) {
-            // File system timestamp only has precision of 1 second, add 1000ms to make up
-            // for the loss of round up.
-            final Event shutdownEvent =
-                    new Event(DEVICE_SHUTDOWN, currentDailyStats.lastTimeSaved + 1000);
+            final Event shutdownEvent = new Event(DEVICE_SHUTDOWN,
+                    Math.max(currentDailyStats.lastTimeSaved, currentDailyStats.endTime));
             shutdownEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
             currentDailyStats.addEvent(shutdownEvent);
-            final Event startupEvent = new Event(DEVICE_STARTUP, currentTimeMillis);
+            final Event startupEvent = new Event(DEVICE_STARTUP, System.currentTimeMillis());
             startupEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
             currentDailyStats.addEvent(startupEvent);
         }
@@ -169,6 +174,54 @@
         persistActiveStats();
     }
 
+    void onPackageRemoved(String packageName, long timeRemoved) {
+        mDatabase.onPackageRemoved(packageName, timeRemoved);
+    }
+
+    private void readPackageMappingsLocked() {
+        mDatabase.readMappingsLocked();
+        cleanUpPackageMappingsLocked();
+    }
+
+    /**
+     * Queries Package Manager for a list of installed packages and removes those packages from
+     * mPackagesTokenData which are not installed any more.
+     * This will only happen once per device boot, when the user is unlocked for the first time.
+     */
+    private void cleanUpPackageMappingsLocked() {
+        final long timeNow = System.currentTimeMillis();
+        /*
+         Note (b/142501248): PackageManagerInternal#getInstalledApplications is not lightweight.
+         Once its implementation is updated, or it's replaced with a better alternative, update
+         the call here to use it. For now, using the heavy #getInstalledApplications is okay since
+         this clean-up is only performed once every boot.
+         */
+        final PackageManagerInternal packageManagerInternal =
+                LocalServices.getService(PackageManagerInternal.class);
+        if (packageManagerInternal == null) {
+            return;
+        }
+        final List<ApplicationInfo> installedPackages =
+                packageManagerInternal.getInstalledApplications(0, mUserId, Process.SYSTEM_UID);
+        // convert the package list to a set for easy look-ups
+        final HashSet<String> packagesSet = new HashSet<>(installedPackages.size());
+        for (int i = installedPackages.size() - 1; i >= 0; i--) {
+            packagesSet.add(installedPackages.get(i).packageName);
+        }
+        final List<String> removedPackages = new ArrayList<>();
+        // populate list of packages that are found in the mappings but not in the installed list
+        for (int i = mDatabase.mPackagesTokenData.packagesToTokensMap.size() - 1; i >= 0; i--) {
+            if (!packagesSet.contains(mDatabase.mPackagesTokenData.packagesToTokensMap.keyAt(i))) {
+                removedPackages.add(mDatabase.mPackagesTokenData.packagesToTokensMap.keyAt(i));
+            }
+        }
+
+        // remove packages in the mappings that are no longer installed
+        for (int i = removedPackages.size() - 1; i >= 0; i--) {
+            mDatabase.mPackagesTokenData.removePackage(removedPackages.get(i), timeNow);
+        }
+    }
+
     private void onTimeChanged(long oldTime, long newTime) {
         persistActiveStats();
         mDatabase.onTimeChanged(newTime - oldTime);
@@ -400,6 +453,7 @@
             if (results == null) {
                 results = new ArrayList<>();
             }
+            mDatabase.filterStats(currentStats);
             combiner.combine(currentStats, true, results);
         }
 
@@ -524,6 +578,8 @@
         if (mStatsChanged) {
             Slog.i(TAG, mLogPrefix + "Flushing usage stats to disk");
             try {
+                mDatabase.obfuscateCurrentStats(mCurrentStats);
+                mDatabase.writeMappingsLocked();
                 for (int i = 0; i < mCurrentStats.length; i++) {
                     mDatabase.putUsageStats(i, mCurrentStats[i]);
                 }
@@ -700,6 +756,10 @@
         mDatabase.dump(ipw, false);
     }
 
+    void dumpMappings(IndentingPrintWriter ipw) {
+        mDatabase.dumpMappings(ipw);
+    }
+
     void dumpFile(IndentingPrintWriter ipw, String[] args) {
         if (args == null || args.length == 0) {
             // dump all files for every interval for specified user
diff --git a/services/usb/java/com/android/server/usb/UsbPermissionManager.java b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
index ef9ee73..1e46f98 100644
--- a/services/usb/java/com/android/server/usb/UsbPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
@@ -20,14 +20,20 @@
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.UserInfo;
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbManager;
 import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.usb.UsbSettingsManagerProto;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.dump.DualDumpOutputStream;
+
+import java.util.List;
 
 class UsbPermissionManager {
     private static final String LOG_TAG = UsbPermissionManager.class.getSimpleName();
@@ -112,4 +118,18 @@
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
+        UserManager userManager = mContext.getSystemService(UserManager.class);
+        synchronized (mPermissionsByUser) {
+            List<UserInfo> users = userManager.getUsers();
+            int numUsers = users.size();
+            for (int i = 0; i < numUsers; i++) {
+                getPermissionsForUser(users.get(i).id).dump(dump, "user_permissions",
+                        UsbSettingsManagerProto.USER_SETTINGS);
+            }
+        }
+        dump.end(token);
+    }
+
 }
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index ce6f592..0493637 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -740,6 +740,8 @@
 
                 mSettingsManager.dump(dump, "settings_manager",
                         UsbServiceDumpProto.SETTINGS_MANAGER);
+                mPermissionManager.dump(dump, "permissions_manager",
+                        UsbServiceDumpProto.PERMISSIONS_MANAGER);
                 dump.flush();
             } else if ("set-port-roles".equals(args[0]) && args.length == 4) {
                 final String portId = args[1];
diff --git a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
index 0cb64a3..e700f19 100644
--- a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
@@ -36,9 +36,12 @@
 import android.os.Environment;
 import android.os.Process;
 import android.os.UserHandle;
-import android.service.usb.UsbSettingsAccessoryPermissionProto;
-import android.service.usb.UsbSettingsDevicePermissionProto;
-import android.service.usb.UsbUserSettingsManagerProto;
+import android.service.usb.UsbAccessoryPermissionProto;
+import android.service.usb.UsbAccessoryPersistentPermissionProto;
+import android.service.usb.UsbDevicePermissionProto;
+import android.service.usb.UsbDevicePersistentPermissionProto;
+import android.service.usb.UsbUidPermissionProto;
+import android.service.usb.UsbUserPermissionsManagerProto;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.Slog;
@@ -261,7 +264,7 @@
             }
 
             if (isChanged) {
-                scheduleWritePermissionLocked();
+                scheduleWritePermissionsLocked();
             }
         }
     }
@@ -288,7 +291,7 @@
             }
 
             if (isChanged) {
-                scheduleWritePermissionLocked();
+                scheduleWritePermissionsLocked();
             }
         }
     }
@@ -370,7 +373,7 @@
     }
 
     @GuardedBy("mLock")
-    private void scheduleWritePermissionLocked() {
+    private void scheduleWritePermissionsLocked() {
         if (mIsCopyPermissionsScheduled) {
             return;
         }
@@ -393,15 +396,18 @@
                 devices = new DeviceFilter[numDevices];
                 uidsForDevices = new int[numDevices][];
                 grantedValuesForDevices = new boolean[numDevices][];
-                for (int i = 0; i < numDevices; i++) {
-                    devices[i] = new DeviceFilter(mDevicePersistentPermissionMap.keyAt(i));
-                    SparseBooleanArray permissions = mDevicePersistentPermissionMap.valueAt(i);
+                for (int deviceIdx = 0; deviceIdx < numDevices; deviceIdx++) {
+                    devices[deviceIdx] =
+                            new DeviceFilter(mDevicePersistentPermissionMap.keyAt(deviceIdx));
+                    SparseBooleanArray permissions =
+                            mDevicePersistentPermissionMap.valueAt(deviceIdx);
                     int numPermissions = permissions.size();
-                    uidsForDevices[i] = new int[numPermissions];
-                    grantedValuesForDevices[i] = new boolean[numPermissions];
-                    for (int j = 0; j < numPermissions; j++) {
-                        uidsForDevices[i][j] = permissions.keyAt(j);
-                        grantedValuesForDevices[i][j] = permissions.valueAt(j);
+                    uidsForDevices[deviceIdx] = new int[numPermissions];
+                    grantedValuesForDevices[deviceIdx] = new boolean[numPermissions];
+                    for (int permissionIdx = 0; permissionIdx < numPermissions; permissionIdx++) {
+                        uidsForDevices[deviceIdx][permissionIdx] = permissions.keyAt(permissionIdx);
+                        grantedValuesForDevices[deviceIdx][permissionIdx] =
+                                permissions.valueAt(permissionIdx);
                     }
                 }
 
@@ -409,16 +415,19 @@
                 accessories = new AccessoryFilter[numAccessories];
                 uidsForAccessories = new int[numAccessories][];
                 grantedValuesForAccessories = new boolean[numAccessories][];
-                for (int i = 0; i < numAccessories; i++) {
-                    accessories[i] =
-                            new AccessoryFilter(mAccessoryPersistentPermissionMap.keyAt(i));
-                    SparseBooleanArray permissions = mAccessoryPersistentPermissionMap.valueAt(i);
+                for (int accessoryIdx = 0; accessoryIdx < numAccessories; accessoryIdx++) {
+                    accessories[accessoryIdx] = new AccessoryFilter(
+                                    mAccessoryPersistentPermissionMap.keyAt(accessoryIdx));
+                    SparseBooleanArray permissions =
+                            mAccessoryPersistentPermissionMap.valueAt(accessoryIdx);
                     int numPermissions = permissions.size();
-                    uidsForAccessories[i] = new int[numPermissions];
-                    grantedValuesForAccessories[i] = new boolean[numPermissions];
-                    for (int j = 0; j < numPermissions; j++) {
-                        uidsForAccessories[i][j] = permissions.keyAt(j);
-                        grantedValuesForAccessories[i][j] = permissions.valueAt(j);
+                    uidsForAccessories[accessoryIdx] = new int[numPermissions];
+                    grantedValuesForAccessories[accessoryIdx] = new boolean[numPermissions];
+                    for (int permissionIdx = 0; permissionIdx < numPermissions; permissionIdx++) {
+                        uidsForAccessories[accessoryIdx][permissionIdx] =
+                                permissions.keyAt(permissionIdx);
+                        grantedValuesForAccessories[accessoryIdx][permissionIdx] =
+                                permissions.valueAt(permissionIdx);
                     }
                 }
                 mIsCopyPermissionsScheduled = false;
@@ -477,22 +486,22 @@
      * Creates UI dialog to request permission for the given package to access the device
      * or accessory.
      *
-     * @param device The USB device attached
-     * @param accessory The USB accessory attached
+     * @param device       The USB device attached
+     * @param accessory    The USB accessory attached
      * @param canBeDefault Whether the calling pacakge can set as default handler
-     * of the USB device or accessory
-     * @param packageName The package name of the calling package
-     * @param uid The uid of the calling package
-     * @param userContext The context to start the UI dialog
-     * @param pi PendingIntent for returning result
+     *                     of the USB device or accessory
+     * @param packageName  The package name of the calling package
+     * @param uid          The uid of the calling package
+     * @param userContext  The context to start the UI dialog
+     * @param pi           PendingIntent for returning result
      */
     void requestPermissionDialog(@Nullable UsbDevice device,
-                                 @Nullable UsbAccessory accessory,
-                                 boolean canBeDefault,
-                                 @NonNull String packageName,
-                                 int uid,
-                                 @NonNull Context userContext,
-                                 @NonNull PendingIntent pi) {
+            @Nullable UsbAccessory accessory,
+            boolean canBeDefault,
+            @NonNull String packageName,
+            int uid,
+            @NonNull Context userContext,
+            @NonNull PendingIntent pi) {
         long identity = Binder.clearCallingIdentity();
         Intent intent = new Intent();
         if (device != null) {
@@ -517,48 +526,96 @@
         }
     }
 
-    void dump(@NonNull DualDumpOutputStream dump) {
+    void dump(@NonNull DualDumpOutputStream dump, String idName, long id) {
+        long token = dump.start(idName, id);
         synchronized (mLock) {
-            for (String deviceName : mDevicePermissionMap.keySet()) {
+            dump.write("user_id", UsbUserPermissionsManagerProto.USER_ID, mUser.getIdentifier());
+            int numMappings = mDevicePermissionMap.size();
+            for (int mappingsIdx = 0; mappingsIdx < numMappings; mappingsIdx++) {
+                String deviceName = mDevicePermissionMap.keyAt(mappingsIdx);
                 long devicePermissionToken = dump.start("device_permissions",
-                        UsbUserSettingsManagerProto.DEVICE_PERMISSIONS);
+                        UsbUserPermissionsManagerProto.DEVICE_PERMISSIONS);
 
-                dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName);
+                dump.write("device_name", UsbDevicePermissionProto.DEVICE_NAME, deviceName);
 
-                SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
-                int count = uidList.size();
-                for (int i = 0; i < count; i++) {
-                    dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i));
+                SparseBooleanArray uidList = mDevicePermissionMap.valueAt(mappingsIdx);
+                int numUids = uidList.size();
+                for (int uidsIdx = 0; uidsIdx < numUids; uidsIdx++) {
+                    dump.write("uids", UsbDevicePermissionProto.UIDS, uidList.keyAt(uidsIdx));
                 }
 
                 dump.end(devicePermissionToken);
             }
 
-            for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) {
+            numMappings = mAccessoryPermissionMap.size();
+            for (int mappingsIdx = 0; mappingsIdx < numMappings; ++mappingsIdx) {
+                UsbAccessory accessory = mAccessoryPermissionMap.keyAt(mappingsIdx);
                 long accessoryPermissionToken = dump.start("accessory_permissions",
-                        UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS);
+                        UsbUserPermissionsManagerProto.ACCESSORY_PERMISSIONS);
 
                 dump.write("accessory_description",
-                        UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
+                        UsbAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
                         accessory.getDescription());
 
-                SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
-                int count = uidList.size();
-                for (int i = 0; i < count; i++) {
-                    dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i));
+                SparseBooleanArray uidList = mAccessoryPermissionMap.valueAt(mappingsIdx);
+                int numUids = uidList.size();
+                for (int uidsIdx = 0; uidsIdx < numUids; uidsIdx++) {
+                    dump.write("uids", UsbAccessoryPermissionProto.UIDS, uidList.keyAt(uidsIdx));
                 }
 
                 dump.end(accessoryPermissionToken);
             }
+
+            numMappings = mDevicePersistentPermissionMap.size();
+            for (int mappingsIdx = 0; mappingsIdx < numMappings; mappingsIdx++) {
+                DeviceFilter filter = mDevicePersistentPermissionMap.keyAt(mappingsIdx);
+                long devicePermissionToken = dump.start("device_persistent_permissions",
+                        UsbUserPermissionsManagerProto.DEVICE_PERSISTENT_PERMISSIONS);
+                filter.dump(dump, "device",
+                        UsbDevicePersistentPermissionProto.DEVICE_FILTER);
+                SparseBooleanArray permissions =
+                        mDevicePersistentPermissionMap.valueAt(mappingsIdx);
+                int numPermissions = permissions.size();
+                for (int permissionsIdx = 0; permissionsIdx < numPermissions; permissionsIdx++) {
+                    long uidPermissionToken = dump.start("uid_permission",
+                            UsbDevicePersistentPermissionProto.PERMISSION_VALUES);
+                    dump.write("uid", UsbUidPermissionProto.UID, permissions.keyAt(permissionsIdx));
+                    dump.write("is_granted",
+                            UsbUidPermissionProto.IS_GRANTED, permissions.valueAt(permissionsIdx));
+                    dump.end(uidPermissionToken);
+                }
+                dump.end(devicePermissionToken);
+            }
+
+            numMappings = mAccessoryPersistentPermissionMap.size();
+            for (int mappingsIdx = 0; mappingsIdx < numMappings; mappingsIdx++) {
+                AccessoryFilter filter = mAccessoryPersistentPermissionMap.keyAt(mappingsIdx);
+                long accessoryPermissionToken = dump.start("accessory_persistent_permissions",
+                        UsbUserPermissionsManagerProto.ACCESSORY_PERSISTENT_PERMISSIONS);
+                filter.dump(dump, "accessory",
+                        UsbAccessoryPersistentPermissionProto.ACCESSORY_FILTER);
+                SparseBooleanArray permissions =
+                        mAccessoryPersistentPermissionMap.valueAt(mappingsIdx);
+                int numPermissions = permissions.size();
+                for (int permissionsIdx = 0; permissionsIdx < numPermissions; permissionsIdx++) {
+                    long uidPermissionToken = dump.start("uid_permission",
+                            UsbAccessoryPersistentPermissionProto.PERMISSION_VALUES);
+                    dump.write("uid", UsbUidPermissionProto.UID, permissions.keyAt(permissionsIdx));
+                    dump.write("is_granted",
+                            UsbUidPermissionProto.IS_GRANTED, permissions.valueAt(permissionsIdx));
+                    dump.end(uidPermissionToken);
+                }
+                dump.end(accessoryPermissionToken);
+            }
         }
+        dump.end(token);
     }
 
     /**
      * Check for camera permission of the calling process.
      *
      * @param packageName Package name of the caller.
-     * @param uid Linux uid of the calling process.
-     *
+     * @param uid         Linux uid of the calling process.
      * @return True in case camera permission is available, False otherwise.
      */
     private boolean isCameraPermissionGranted(String packageName, int uid) {
@@ -677,7 +734,7 @@
      *
      * @param device The device that needs to get scanned
      * @return True in case a VIDEO device or interface is present,
-     *         False otherwise.
+     * False otherwise.
      */
     private boolean isCameraDevicePresent(UsbDevice device) {
         if (device.getDeviceClass() == UsbConstants.USB_CLASS_VIDEO) {
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java b/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java
index 0535d71..ff7f393 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java
@@ -52,6 +52,7 @@
                                                 int length, byte type) {
         UsbInterfaceDescriptor interfaceDesc = parser.getCurInterface();
         int subClass = interfaceDesc.getUsbSubclass();
+        // TODO shouldn't this switch on subtype?
         switch (subClass) {
             case AUDIO_AUDIOCONTROL:
                 if (UsbDescriptorParser.DEBUG) {
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
index 8e7babb..b230e4b 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -26,7 +26,7 @@
  */
 public final class UsbDescriptorParser {
     private static final String TAG = "UsbDescriptorParser";
-    public static final boolean DEBUG = true;
+    public static final boolean DEBUG = false;
 
     private final String mDeviceAddr;
 
@@ -43,6 +43,11 @@
     // Obtained from the first AudioClass Header descriptor.
     private int mACInterfacesSpec = UsbDeviceDescriptor.USBSPEC_1_0;
 
+    // The VideoClass spec implemented by the VideoClass Interfaces
+    // This may well be different than the overall USB Spec.
+    // Obtained from the first VidieoClass Header descriptor.
+    private int mVCInterfacesSpec = UsbDeviceDescriptor.USBSPEC_1_0;
+
     /**
      * Connect this parser to an existing set of already parsed descriptors.
      * This is useful for reporting.
@@ -90,6 +95,14 @@
         return mACInterfacesSpec;
     }
 
+    public void setVCInterfaceSpec(int spec) {
+        mVCInterfacesSpec = spec;
+    }
+
+    public int getVCInterfaceSpec() {
+        return mVCInterfacesSpec;
+    }
+
     private class UsbDescriptorsStreamFormatException extends Exception {
         String mMessage;
         UsbDescriptorsStreamFormatException(String message) {
@@ -186,19 +199,20 @@
                             break;
 
                         case UsbDescriptor.CLASSID_VIDEO:
-                            Log.d(TAG, "  UsbDescriptor.CLASSID_VIDEO subType:0x"
-                                    + Integer.toHexString(stream.getByte()));
+                            if (DEBUG) {
+                                Log.d(TAG, "  UsbDescriptor.CLASSID_VIDEO");
+                            }
                             descriptor = UsbVCInterface.allocDescriptor(this, stream, length, type);
                             break;
 
                         case UsbDescriptor.CLASSID_AUDIOVIDEO:
-                            Log.d(TAG, "  UsbDescriptor.CLASSID_AUDIOVIDEO subType:0x"
-                                    + Integer.toHexString(stream.getByte()));
+                            if (DEBUG) {
+                                Log.d(TAG, "  UsbDescriptor.CLASSID_AUDIOVIDEO");
+                            }
                             break;
 
                         default:
-                            Log.d(TAG, "  Unparsed Class-specific Interface:0x"
-                                    + Integer.toHexString(mCurInterfaceDescriptor.getUsbClass()));
+                            Log.w(TAG, "  Unparsed Class-specific");
                             break;
                     }
                 }
@@ -206,23 +220,32 @@
 
             case UsbDescriptor.DESCRIPTORTYPE_CLASSSPECIFIC_ENDPOINT:
                 if (mCurInterfaceDescriptor != null) {
-                    switch (mCurInterfaceDescriptor.getUsbClass()) {
+                    int subClass = mCurInterfaceDescriptor.getUsbClass();
+                    switch (subClass) {
                         case UsbDescriptor.CLASSID_AUDIO:
                             descriptor = UsbACEndpoint.allocDescriptor(this, length, type);
                             break;
-                        case UsbDescriptor.CLASSID_VIDEO:
-                            Log.d(TAG, "UsbDescriptor.CLASSID_VIDEO subType:0x"
-                                    + Integer.toHexString(stream.getByte()));
-                            descriptor = UsbVCEndpoint.allocDescriptor(this, length, type);
+
+                        case UsbDescriptor.CLASSID_VIDEO: {
+                            Byte subtype = stream.getByte();
+                            if (DEBUG) {
+                                Log.d(TAG, "UsbDescriptor.CLASSID_VIDEO type:0x"
+                                        + Integer.toHexString(type));
+                            }
+                            descriptor = UsbVCEndpoint.allocDescriptor(this, length, type, subtype);
+                        }
                             break;
 
                         case UsbDescriptor.CLASSID_AUDIOVIDEO:
-                            Log.d(TAG, "UsbDescriptor.CLASSID_AUDIOVIDEO subType:0x"
-                                    + Integer.toHexString(stream.getByte()));
+                            if (DEBUG) {
+                                Log.d(TAG, "UsbDescriptor.CLASSID_AUDIOVIDEO type:0x"
+                                        + Integer.toHexString(type));
+                            }
                             break;
+
                         default:
-                            Log.d(TAG, "  Unparsed Class-specific Endpoint:0x"
-                                    + Integer.toHexString(mCurInterfaceDescriptor.getUsbClass()));
+                            Log.w(TAG, "  Unparsed Class-specific Endpoint:0x"
+                                    + Integer.toHexString(subClass));
                             break;
                     }
                 }
@@ -555,6 +578,30 @@
     /**
      * @hide
      */
+    public boolean hasVideoCapture() {
+        for (UsbDescriptor descriptor : mDescriptors) {
+            if (descriptor instanceof UsbVCInputTerminal) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @hide
+     */
+    public boolean hasVideoPlayback() {
+        for (UsbDescriptor descriptor : mDescriptors) {
+            if (descriptor instanceof UsbVCOutputTerminal) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @hide
+     */
     public boolean hasHIDInterface() {
         ArrayList<UsbDescriptor> descriptors =
                 getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_HID);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
index 9739243..b1cbbaf 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
@@ -160,7 +160,8 @@
         return new UsbDevice.Builder(parser.getDeviceAddr(), mVendorID,
                 mProductID, mDevClass, mDevSubClass, mProtocol, mfgName, prodName, versionString,
                 configs, serialStr, parser.hasAudioPlayback(), parser.hasAudioCapture(),
-                parser.hasMIDIInterface());
+                parser.hasMIDIInterface(),
+                parser.hasVideoPlayback(), parser.hasVideoCapture());
     }
 
     @Override
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCEndpoint.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCEndpoint.java
index 39fbc0d..f9acece 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbVCEndpoint.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCEndpoint.java
@@ -20,41 +20,54 @@
 /**
  * @hide
  * A video class-specific Endpoint
- * see
+ * see USB_Video_Class_1.1.pdf - 3.10 VideoStreaming Endpoint Descriptors
  */
 abstract class UsbVCEndpoint extends UsbDescriptor {
     private static final String TAG = "UsbVCEndpoint";
 
-    UsbVCEndpoint(int length, byte type, int subclass) {
+
+    public static final byte VCEP_UNDEFINED = 0x00;
+    public static final byte VCEP_GENERAL   = 0x01;
+    public static final byte VCEP_ENDPOINT  = 0x02;
+    public static final byte VCEP_INTERRUPT = 0x03;
+
+    UsbVCEndpoint(int length, byte type) {
         super(length, type);
-        // mSubclass = subclass;
     }
 
     public static UsbDescriptor allocDescriptor(UsbDescriptorParser parser,
-                                                int length, byte type) {
+                                                int length, byte type, byte subtype) {
         UsbInterfaceDescriptor interfaceDesc = parser.getCurInterface();
-        int subClass = interfaceDesc.getUsbSubclass();
-        switch (subClass) {
-//            case AUDIO_AUDIOCONTROL:
-//                if (UsbDescriptorParser.DEBUG) {
-//                    Log.i(TAG, "---> AUDIO_AUDIOCONTROL");
-//                }
-//                return new UsbACAudioControlEndpoint(length, type, subClass);
-//
-//            case AUDIO_AUDIOSTREAMING:
-//                if (UsbDescriptorParser.DEBUG) {
-//                    Log.i(TAG, "---> AUDIO_AUDIOSTREAMING");
-//                }
-//                return new UsbACAudioStreamEndpoint(length, type, subClass);
-//
-//            case AUDIO_MIDISTREAMING:
-//                if (UsbDescriptorParser.DEBUG) {
-//                    Log.i(TAG, "---> AUDIO_MIDISTREAMING");
-//                }
-//                return new UsbACMidiEndpoint(length, type, subClass);
+
+        // TODO - create classes for each specific subtype
+        //  (don't need it to answer if this device supports video
+        switch (subtype) {
+            case VCEP_UNDEFINED:
+                if (UsbDescriptorParser.DEBUG) {
+                    Log.d(TAG, "---> VCEP_UNDEFINED");
+                }
+                return null;
+
+            case VCEP_GENERAL:
+                if (UsbDescriptorParser.DEBUG) {
+                    Log.d(TAG, "---> VCEP_GENERAL");
+                }
+                return null;
+
+            case VCEP_ENDPOINT:
+                if (UsbDescriptorParser.DEBUG) {
+                    Log.d(TAG, "---> VCEP_ENDPOINT");
+                }
+                return null;
+
+            case VCEP_INTERRUPT:
+                if (UsbDescriptorParser.DEBUG) {
+                    Log.d(TAG, "---> VCEP_INTERRUPT");
+                }
+                return null;
 
             default:
-                Log.w(TAG, "Unknown Video Class Endpoint id:0x" + Integer.toHexString(subClass));
+                Log.w(TAG, "Unknown Video Class Endpoint id:0x" + Integer.toHexString(subtype));
                 return null;
         }
     }
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCHeader.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCHeader.java
new file mode 100644
index 0000000..3fc4224
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCHeader.java
@@ -0,0 +1,50 @@
+/*
+ * 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.usb.descriptors;
+
+import android.util.Log;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * A video class-specific Interface Header.
+ * see USB_Video_Class_1.1.pdf section 3.9.2 - Class-Specific VS Interface Descriptors
+ */
+public final class UsbVCHeader extends UsbVCHeaderInterface {
+    private static final String TAG = "UsbVCHeader";
+
+    // TODO Add data members for this descriptor's data
+
+    public UsbVCHeader(int length, byte type, byte subtype, int spec) {
+        super(length, type, subtype, spec);
+    }
+
+    @Override
+    public int parseRawDescriptors(ByteStream stream) {
+        if (UsbDescriptorParser.DEBUG) {
+            Log.d(TAG, " ---> parseRawDescriptors()");
+        }
+        // TODO parse data members for this descriptor's data
+        return super.parseRawDescriptors(stream);
+    }
+
+    @Override
+    public void report(ReportCanvas canvas) {
+        super.report(canvas);
+        // TODO add reporting specific to this descriptor
+    }
+}
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCHeaderInterface.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCHeaderInterface.java
new file mode 100644
index 0000000..3725091
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCHeaderInterface.java
@@ -0,0 +1,56 @@
+/*
+ * 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.usb.descriptors;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * A video class-specific Interface Header super class.
+ * see USB_Video_Class_1.1.pdf section 3.9.2 - Class-Specific VS Interface Descriptors
+ */
+public abstract class UsbVCHeaderInterface extends UsbVCInterface {
+    private static final String TAG = "UsbVCHeaderInterface";
+
+    protected int mVDCRelease;  // Video Device Class Specification Release (BCD).
+    protected int mTotalLength; // Total number of bytes returned for the class-specific
+    // VideoControl interface descriptor. Includes the combined length
+    // of this descriptor header and all Unit and Terminal descriptors.
+
+    public UsbVCHeaderInterface(
+            int length, byte type, byte subtype, int vdcRelease) {
+        super(length, type, subtype);
+        mVDCRelease = vdcRelease;
+    }
+
+    public int getVDCRelease() {
+        return mVDCRelease;
+    }
+
+    public int getTotalLength() {
+        return mTotalLength;
+    }
+
+    @Override
+    public void report(ReportCanvas canvas) {
+        super.report(canvas);
+
+        canvas.openList();
+        canvas.writeListItem("Release: " + ReportCanvas.getBCDString(getVDCRelease()));
+        canvas.writeListItem("Total Length: " + getTotalLength());
+        canvas.closeList();
+    }
+}
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCInputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCInputTerminal.java
new file mode 100644
index 0000000..df63795
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCInputTerminal.java
@@ -0,0 +1,49 @@
+/*
+ * 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.usb.descriptors;
+
+import android.util.Log;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * A video class-specific Input terminal interface.
+ * see USB_Video_Class_1.1.pdf section 3.7.2.1 Input Terminal Descriptor
+ */
+public final class UsbVCInputTerminal extends UsbVCInterface {
+    private static final String TAG = "UsbVCInputTerminal";
+
+    // TODO Define members to hold the data from this descriptor
+    public UsbVCInputTerminal(int length, byte type, byte subtype) {
+        super(length, type, subtype);
+    }
+
+    @Override
+    public int parseRawDescriptors(ByteStream stream) {
+        // TODO Parse the data from this descriptor
+        if (UsbDescriptorParser.DEBUG) {
+            Log.d(TAG, " ---> parseRawDescriptors()");
+        }
+        return super.parseRawDescriptors(stream);
+    }
+
+    @Override
+    public void report(ReportCanvas canvas) {
+        // TODO Add reporting specific to this descriptor
+        super.report(canvas);
+    }
+};
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCInterface.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCInterface.java
index c9eb1ec..46263dd 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbVCInterface.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCInterface.java
@@ -29,20 +29,17 @@
     public static final byte VCI_UNDEFINED          = 0x00;
     public static final byte VCI_VEADER             = 0x01;
     public static final byte VCI_INPUT_TERMINAL     = 0x02;
-    public static final byte VCI_VOUTPUT_TERMINAL   = 0x03;
+    public static final byte VCI_OUTPUT_TERMINAL    = 0x03;
     public static final byte VCI_SELECTOR_UNIT      = 0x04;
-    public static final byte VCI_VROCESSING_UNIT    = 0x05;
-    public static final byte VCI_VEXTENSION_UNIT    = 0x06;
+    public static final byte VCI_PROCESSING_UNIT    = 0x05;
+    public static final byte VCI_EXTENSION_UNIT     = 0x06;
 
-   // See “Universal Serial Bus Device Class Definition for Video
+    // See “Universal Serial Bus Device Class Definition for Video
     protected final byte mSubtype;  // 2:1 HEADER descriptor subtype
-    protected final int mSubclass;  // from the mSubclass member of the
-    // "enclosing" Interface Descriptor
 
-    public UsbVCInterface(int length, byte type, byte subtype, int subclass) {
+    public UsbVCInterface(int length, byte type, byte subtype) {
         super(length, type);
         mSubtype = subtype;
-        mSubclass = subclass;
     }
 
     /**
@@ -52,12 +49,10 @@
                                                 int length, byte type) {
         byte subtype = stream.getByte();
         UsbInterfaceDescriptor interfaceDesc = parser.getCurInterface();
-        int subClass = interfaceDesc.getUsbSubclass();
         if (UsbDescriptorParser.DEBUG) {
-            Log.d(TAG, "  Video Class-specific Interface subClass:0x"
-                    + Integer.toHexString(subClass));
+            Log.d(TAG, "  Video Class-specific Interface subtype: " + subtype);
         }
-        switch (subClass) {
+        switch (subtype) {
             // TODO - Create descriptor classes and parse these...
             case VCI_UNDEFINED:
                 if (UsbDescriptorParser.DEBUG) {
@@ -66,44 +61,51 @@
                 break;
 
             case VCI_VEADER:
+            {
                 if (UsbDescriptorParser.DEBUG) {
                     Log.d(TAG, " ---> VCI_VEADER");
                 }
-                break;
+                int vcInterfaceSpec = stream.unpackUsbShort();
+                parser.setVCInterfaceSpec(vcInterfaceSpec);
+                if (UsbDescriptorParser.DEBUG) {
+                    Log.d(TAG, "  vcInterfaceSpec:0x" + Integer.toHexString(vcInterfaceSpec));
+                }
+                return new UsbVCHeader(length, type, subtype, vcInterfaceSpec);
+            }
 
             case VCI_INPUT_TERMINAL:
                 if (UsbDescriptorParser.DEBUG) {
                     Log.d(TAG, " ---> VCI_INPUT_TERMINAL");
                 }
-                break;
+                return new UsbVCInputTerminal(length, type, subtype);
 
-            case VCI_VOUTPUT_TERMINAL:
+            case VCI_OUTPUT_TERMINAL:
                 if (UsbDescriptorParser.DEBUG) {
-                    Log.d(TAG, " ---> VCI_VOUTPUT_TERMINAL");
+                    Log.d(TAG, " ---> VCI_OUTPUT_TERMINAL");
                 }
-                break;
+                return new UsbVCOutputTerminal(length, type, subtype);
 
             case VCI_SELECTOR_UNIT:
                 if (UsbDescriptorParser.DEBUG) {
                     Log.d(TAG, " ---> VCI_SELECTOR_UNIT");
                 }
-                break;
+                return new UsbVCSelectorUnit(length, type, subtype);
 
-            case VCI_VROCESSING_UNIT:
+            case VCI_PROCESSING_UNIT:
                 if (UsbDescriptorParser.DEBUG) {
-                    Log.d(TAG, " ---> VCI_VROCESSING_UNIT");
+                    Log.d(TAG, " ---> VCI_PROCESSING_UNIT");
                 }
-                break;
+                return new UsbVCProcessingUnit(length, type, subtype);
 
-            case VCI_VEXTENSION_UNIT:
+            case VCI_EXTENSION_UNIT:
                 if (UsbDescriptorParser.DEBUG) {
-                    Log.d(TAG, " ---> VCI_VEXTENSION_UNIT");
+                    Log.d(TAG, " ---> VCI_EXTENSION_UNIT");
                 }
                 break;
 
             default:
-                Log.w(TAG, "Unknown Video Class Interface Subclass: 0x"
-                        + Integer.toHexString(subClass));
+                Log.w(TAG, "Unknown Video Class Interface subtype: 0x"
+                        + Integer.toHexString(subtype));
                 return null;
         }
 
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCOutputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCOutputTerminal.java
new file mode 100644
index 0000000..4aa8ca2
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCOutputTerminal.java
@@ -0,0 +1,49 @@
+/*
+ * 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.usb.descriptors;
+
+import android.util.Log;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * A video class-specific Output Terminal Descriptor.
+ * see USB_Video_Class_1.1.pdf section 3.7.2.2 Output Terminal Descriptor
+ */
+public final class UsbVCOutputTerminal extends UsbVCInterface {
+    private static final String TAG = "UsbVCOutputTerminal";
+
+    // TODO Add members for the data in this descriptor
+    public UsbVCOutputTerminal(int length, byte type, byte subtype) {
+        super(length, type, subtype);
+    }
+
+    @Override
+    public int parseRawDescriptors(ByteStream stream) {
+        // TODO Parse the data in this descriptor
+        if (UsbDescriptorParser.DEBUG) {
+            Log.d(TAG, " ---> parseRawDescriptors()");
+        }
+        return super.parseRawDescriptors(stream);
+    }
+
+    @Override
+    public void report(ReportCanvas canvas) {
+        super.report(canvas);
+        // TODO Add reporting specific to this descriptor
+    }
+};
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCProcessingUnit.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCProcessingUnit.java
new file mode 100644
index 0000000..5ce842e
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCProcessingUnit.java
@@ -0,0 +1,50 @@
+/*
+ * 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.usb.descriptors;
+
+import android.util.Log;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An video class-specific Processing Unit Interface.
+ * see USB_Video_Class_1.1.pdf section Table 3-8 Processing Unit Descriptor
+ */
+public final class UsbVCProcessingUnit extends UsbVCInterface {
+    private static final String TAG = "UsbVCProcessingUnit";
+
+    // TODO Add data members for this descriptor
+
+    public UsbVCProcessingUnit(int length, byte type, byte subtype) {
+        super(length, type, subtype);
+    }
+
+    @Override
+    public int parseRawDescriptors(ByteStream stream) {
+        // TODO Parse this descriptor
+        if (UsbDescriptorParser.DEBUG) {
+            Log.d(TAG, " ---> parseRawDescriptors()");
+        }
+        return super.parseRawDescriptors(stream);
+    }
+
+    @Override
+    public void report(ReportCanvas canvas) {
+        super.report(canvas);
+        // TODO Add reporting specific to this descriptor
+    }
+};
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCSelectorUnit.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCSelectorUnit.java
new file mode 100644
index 0000000..8e9b0d8
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCSelectorUnit.java
@@ -0,0 +1,50 @@
+/*
+ * 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.usb.descriptors;
+
+import android.util.Log;
+
+import com.android.server.usb.descriptors.report.ReportCanvas;
+
+/**
+ * @hide
+ * An video class-specific Selector Unit Descriptor
+ * see USB_Video_Class_1.1.pdf section 3.7.2.4
+ */
+public final class UsbVCSelectorUnit extends UsbVCInterface {
+    private static final String TAG = "UsbVCSelectorUnit";
+
+    // TODO Add data members for this descriptor
+
+    public UsbVCSelectorUnit(int length, byte type, byte subtype) {
+        super(length, type, subtype);
+    }
+
+    @Override
+    public int parseRawDescriptors(ByteStream stream) {
+        // TODO Parse this descriptor
+        if (UsbDescriptorParser.DEBUG) {
+            Log.d(TAG, " ---> parseRawDescriptors()");
+        }
+        return super.parseRawDescriptors(stream);
+    }
+
+    @Override
+    public void report(ReportCanvas canvas) {
+        super.report(canvas);
+        // TODO Add reporting specific to this descriptor
+    }
+};
diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp
index 2ff26b8..3f20273 100644
--- a/startop/apps/test/Android.bp
+++ b/startop/apps/test/Android.bp
@@ -18,9 +18,12 @@
     name: "startop_test_app",
     srcs: [
         "src/ComplexLayoutInflationActivity.java",
-        "src/CPUIntensive.java",
+        "src/CPUIntensiveBenchmarkActivity.java",
+        "src/CPUIntensiveBenchmarks.java",
         "src/EmptyActivity.java",
         "src/FrameLayoutInflationActivity.java",
+        "src/InitCheckOverheadBenchmarkActivity.java",
+        "src/InitCheckOverheadBenchmarks.java",
         "src/LayoutInflationActivity.java",
         "src/NonInteractiveSystemServerBenchmarkActivity.java",
         "src/SystemServerBenchmarkActivity.java",
diff --git a/startop/apps/test/AndroidManifest.xml b/startop/apps/test/AndroidManifest.xml
index ebe2584..235aa0d 100644
--- a/startop/apps/test/AndroidManifest.xml
+++ b/startop/apps/test/AndroidManifest.xml
@@ -37,6 +37,18 @@
         </activity>
 
         <activity
+            android:label="CPU Intensive Benchmark Test"
+            android:name=".CPUIntensiveBenchmarkActivity"
+            android:exported="true" >
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
             android:label="Empty Activity Layout Test"
             android:name=".EmptyActivity"
             android:exported="true" >
@@ -61,6 +73,18 @@
         </activity>
 
         <activity
+            android:label="Initialization Check Overhead Test"
+            android:name=".InitCheckOverheadBenchmarkActivity"
+            android:exported="true" >
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
             android:label="TextView Layout Test"
             android:name=".TextViewInflationActivity"
             android:exported="true" >
diff --git a/startop/apps/test/src/CPUIntensive.java b/startop/apps/test/src/CPUIntensive.java
deleted file mode 100644
index a411e8c..0000000
--- a/startop/apps/test/src/CPUIntensive.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-/**
- *  A threaded CPU intensive class for use in benchmarks.
- */
-
-package com.android.startop.test;
-
-final class CPUIntensive {
-    public static final int THREAD_COUNT = 8;
-    public static final int ARRAY_SIZE = 30000;
-    public static int[][] array = new int[THREAD_COUNT][ARRAY_SIZE];
-
-    static class WorkerThread extends Thread {
-        int mThreadNumber;
-        WorkerThread(int number) {
-            mThreadNumber = number;
-        }
-        public void run() {
-            final int arrayLength = array[mThreadNumber].length;
-            for (int i = 0; i < arrayLength; ++i) {
-                array[mThreadNumber][i] = i * i;
-            }
-            for (int i = 0; i < arrayLength; ++i) {
-                for (int j = 0; j < arrayLength; ++j) {
-                    int swap = array[mThreadNumber][j];
-                    array[mThreadNumber][j] = array[mThreadNumber][(j + i) % arrayLength];
-                    array[mThreadNumber][(j + i) % arrayLength] = swap;
-                }
-            }
-        }
-    };
-
-    public static void doSomeWork(int threadCount) {
-        WorkerThread[] threads = new WorkerThread[threadCount];
-        // Create the threads.
-        for (int i = 0; i < threadCount; ++i) {
-            threads[i] = new WorkerThread(i);
-        }
-        // Start the threads.
-        for (int i = 0; i < threadCount; ++i) {
-            threads[i].start();
-        }
-        // Join the threads.
-        for (int i = 0; i < threadCount; ++i) {
-            try {
-                threads[i].join();
-            } catch (Exception ex) {
-            }
-        }
-    }
-}
-
diff --git a/startop/apps/test/src/CPUIntensiveBenchmarkActivity.java b/startop/apps/test/src/CPUIntensiveBenchmarkActivity.java
new file mode 100644
index 0000000..2ec5308
--- /dev/null
+++ b/startop/apps/test/src/CPUIntensiveBenchmarkActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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.startop.test;
+
+import android.os.Bundle;
+
+public class CPUIntensiveBenchmarkActivity extends SystemServerBenchmarkActivity {
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.system_server_benchmark_page);
+
+        mBenchmarkList = findViewById(R.id.benchmark_list);
+
+        CPUIntensiveBenchmarks.initializeBenchmarks(this, this);
+    }
+}
diff --git a/startop/apps/test/src/CPUIntensiveBenchmarks.java b/startop/apps/test/src/CPUIntensiveBenchmarks.java
new file mode 100644
index 0000000..19d0b63
--- /dev/null
+++ b/startop/apps/test/src/CPUIntensiveBenchmarks.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+/**
+ *  A threaded CPU intensive class for use in benchmarks.
+ */
+
+package com.android.startop.test;
+
+import android.app.Activity;
+
+public class CPUIntensiveBenchmarks {
+    public static final int ARRAY_SIZE = 30000;
+    public static int[][] mArray;
+
+    static class WorkerThread extends Thread {
+        int mThreadNumber;
+        WorkerThread(int number) {
+            mThreadNumber = number;
+        }
+        public void run() {
+            final int arrayLength = mArray[mThreadNumber].length;
+            for (int i = 0; i < arrayLength; ++i) {
+                mArray[mThreadNumber][i] = i * i;
+            }
+            for (int i = 0; i < arrayLength; ++i) {
+                for (int j = 0; j < arrayLength; ++j) {
+                    int swap = mArray[mThreadNumber][j];
+                    mArray[mThreadNumber][j] = mArray[mThreadNumber][(j + i) % arrayLength];
+                    mArray[mThreadNumber][(j + i) % arrayLength] = swap;
+                }
+            }
+        }
+    };
+
+    static void doSomeWork(int threadCount) {
+        mArray = new int[threadCount][ARRAY_SIZE];
+        WorkerThread[] threads = new WorkerThread[threadCount];
+        // Create the threads.
+        for (int i = 0; i < threadCount; ++i) {
+            threads[i] = new WorkerThread(i);
+        }
+        // Start the threads.
+        for (int i = 0; i < threadCount; ++i) {
+            threads[i].start();
+        }
+        // Join the threads.
+        for (int i = 0; i < threadCount; ++i) {
+            try {
+                threads[i].join();
+            } catch (Exception ex) {
+            }
+        }
+    }
+
+    // Time limit to run benchmarks in seconds
+    public static final int TIME_LIMIT = 5;
+
+    static void initializeBenchmarks(Activity parent, BenchmarkRunner benchmarks) {
+        benchmarks.addBenchmark("Use 1 thread", () -> {
+            doSomeWork(1);
+        });
+        benchmarks.addBenchmark("Use 2 threads", () -> {
+            doSomeWork(2);
+        });
+        benchmarks.addBenchmark("Use 4 threads", () -> {
+            doSomeWork(4);
+        });
+        benchmarks.addBenchmark("Use 8 threads", () -> {
+            doSomeWork(8);
+        });
+        benchmarks.addBenchmark("Use 16 threads", () -> {
+            doSomeWork(16);
+        });
+    }
+}
diff --git a/startop/apps/test/src/InitCheckOverheadBenchmarkActivity.java b/startop/apps/test/src/InitCheckOverheadBenchmarkActivity.java
new file mode 100644
index 0000000..3e0e3b1
--- /dev/null
+++ b/startop/apps/test/src/InitCheckOverheadBenchmarkActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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.startop.test;
+
+import android.os.Bundle;
+
+public class InitCheckOverheadBenchmarkActivity extends SystemServerBenchmarkActivity {
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.system_server_benchmark_page);
+
+        mBenchmarkList = findViewById(R.id.benchmark_list);
+
+        InitCheckOverheadBenchmarks.initializeBenchmarks(this, this);
+    }
+}
diff --git a/startop/apps/test/src/InitCheckOverheadBenchmarks.java b/startop/apps/test/src/InitCheckOverheadBenchmarks.java
new file mode 100644
index 0000000..79adbbc
--- /dev/null
+++ b/startop/apps/test/src/InitCheckOverheadBenchmarks.java
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+/**
+ *  A test of initialization check costs for AOT.
+ */
+
+package com.android.startop.test;
+
+import android.app.Activity;
+
+import java.util.Random;
+
+public class InitCheckOverheadBenchmarks {
+    public static int mSum;
+    public static int mSum2;
+    public static int mStep;
+    public static int mStep2;
+    public static int mStartingValue;
+
+    static {
+        Random random = new Random();
+        mStep = random.nextInt();
+        mStep2 = random.nextInt();
+        mStartingValue = random.nextInt();
+    };
+
+    static class OtherClass {
+        public static int mStep;
+        public static int mStep2;
+        public static int mStartingValue;
+        static {
+            Random random = new Random();
+            mStep = random.nextInt();
+            mStep2 = random.nextInt();
+            mStartingValue = random.nextInt();
+        };
+    };
+
+    public static void localStaticFor(int iterationCount) {
+        for (int i = 0; i < iterationCount; ++i) {
+            mSum += mStep;
+        }
+    }
+
+    public static void nonLocalStaticFor(int iterationCount) {
+        mSum = OtherClass.mStartingValue;
+        for (int i = 0; i < iterationCount; ++i) {
+            mSum += OtherClass.mStep;
+        }
+    }
+
+    public static void localStaticForTwo(int iterationCount) {
+        for (int i = 0; i < iterationCount; ++i) {
+            mSum += mStep;
+            mSum2 += mStep2;
+        }
+    }
+
+    public static void nonLocalStaticForTwo(int iterationCount) {
+        mSum = OtherClass.mStartingValue;
+        for (int i = 0; i < iterationCount; ++i) {
+            mSum += OtherClass.mStep;
+            mSum2 += OtherClass.mStep2;
+        }
+    }
+
+    public static void localStaticDoWhile(int iterationCount) {
+        int i = 0;
+        do {
+            mSum += mStep;
+            ++i;
+        } while (i < iterationCount);
+    }
+
+    public static void nonLocalStaticDoWhile(int iterationCount) {
+        mSum = OtherClass.mStartingValue;
+        int i = 0;
+        do {
+            mSum += OtherClass.mStep;
+            ++i;
+        } while (i < iterationCount);
+    }
+
+    public static void doGC() {
+        Runtime.getRuntime().gc();
+    }
+
+    // Time limit to run benchmarks in seconds
+    public static final int TIME_LIMIT = 5;
+
+    static void initializeBenchmarks(Activity parent, BenchmarkRunner benchmarks) {
+        benchmarks.addBenchmark("GC", () -> {
+            doGC();
+        });
+
+        benchmarks.addBenchmark("InitCheckFor (local)", () -> {
+            localStaticFor(10000000);
+        });
+
+        benchmarks.addBenchmark("InitCheckFor (non-local)", () -> {
+            nonLocalStaticFor(10000000);
+        });
+
+        benchmarks.addBenchmark("InitCheckForTwo (local)", () -> {
+            localStaticForTwo(10000000);
+        });
+
+        benchmarks.addBenchmark("InitCheckForTwo (non-local)", () -> {
+            nonLocalStaticForTwo(10000000);
+        });
+
+        benchmarks.addBenchmark("InitCheckDoWhile (local)", () -> {
+            localStaticDoWhile(10000000);
+        });
+
+        benchmarks.addBenchmark("InitCheckDoWhile (non-local)", () -> {
+            nonLocalStaticDoWhile(10000000);
+        });
+    }
+}
diff --git a/startop/apps/test/src/SystemServerBenchmarkActivity.java b/startop/apps/test/src/SystemServerBenchmarkActivity.java
index 75ea69b..6be8df3 100644
--- a/startop/apps/test/src/SystemServerBenchmarkActivity.java
+++ b/startop/apps/test/src/SystemServerBenchmarkActivity.java
@@ -17,28 +17,20 @@
 package com.android.startop.test;
 
 import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.GridLayout;
 import android.widget.TextView;
 
 public class SystemServerBenchmarkActivity extends Activity implements BenchmarkRunner {
-    private GridLayout benchmarkList;
+    protected GridLayout mBenchmarkList;
 
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.system_server_benchmark_page);
 
-        benchmarkList = findViewById(R.id.benchmark_list);
+        mBenchmarkList = findViewById(R.id.benchmark_list);
 
         SystemServerBenchmarks.initializeBenchmarks(this, this);
     }
@@ -49,7 +41,7 @@
      * @param name A short name that shows up in the UI or benchmark results
      */
     public void addBenchmark(CharSequence name, Runnable thunk) {
-        Context context = benchmarkList.getContext();
+        Context context = mBenchmarkList.getContext();
         Button button = new Button(context);
         TextView mean = new TextView(context);
         TextView stdev = new TextView(context);
@@ -68,8 +60,8 @@
             });
         });
 
-        benchmarkList.addView(button);
-        benchmarkList.addView(mean);
-        benchmarkList.addView(stdev);
+        mBenchmarkList.addView(button);
+        mBenchmarkList.addView(mean);
+        mBenchmarkList.addView(stdev);
     }
 }
diff --git a/startop/apps/test/src/SystemServerBenchmarks.java b/startop/apps/test/src/SystemServerBenchmarks.java
index 5918503..25b43f4 100644
--- a/startop/apps/test/src/SystemServerBenchmarks.java
+++ b/startop/apps/test/src/SystemServerBenchmarks.java
@@ -60,22 +60,6 @@
         benchmarks.addBenchmark("Empty", () -> {
         });
 
-        benchmarks.addBenchmark("CPU Intensive (1 thread)", () -> {
-            CPUIntensive.doSomeWork(1);
-        });
-
-        benchmarks.addBenchmark("CPU Intensive (2 thread)", () -> {
-            CPUIntensive.doSomeWork(2);
-        });
-
-        benchmarks.addBenchmark("CPU Intensive (4 thread)", () -> {
-            CPUIntensive.doSomeWork(4);
-        });
-
-        benchmarks.addBenchmark("CPU Intensive (8 thread)", () -> {
-            CPUIntensive.doSomeWork(8);
-        });
-
         PackageManager pm = parent.getPackageManager();
         benchmarks.addBenchmark("getInstalledApplications", () -> {
             pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY);
diff --git a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java b/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
index cf120cf..59f4d56 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
@@ -33,6 +33,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -162,8 +163,8 @@
         @Override
         public boolean equals(Object other) {
             if (other instanceof BaseWithActivityRecordData) {
-                return activityRecordSnapshot.equals(
-                        ((BaseWithActivityRecordData)other).activityRecordSnapshot) &&
+                return (Arrays.equals(activityRecordSnapshot,
+                      ((BaseWithActivityRecordData)other).activityRecordSnapshot)) &&
                         super.equals(other);
             }
             return false;
@@ -171,7 +172,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", " + activityRecordSnapshot.toString();
+            return ", " + new String(activityRecordSnapshot);
         }
 
         @Override
@@ -208,7 +209,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", temperature=" + Integer.toString(temperature);
+            return super.toStringBody() + ", temperature=" + Integer.toString(temperature);
         }
 
         @Override
@@ -235,7 +236,7 @@
 
         @Override
         public boolean equals(Object other) {
-            if (other instanceof ActivityLaunched) {
+            if (other instanceof ActivityLaunchFinished) {
                 return timestampNs == ((ActivityLaunchFinished)other).timestampNs &&
                        super.equals(other);
             }
@@ -244,7 +245,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", timestampNs=" + Long.toString(timestampNs);
+            return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
         }
 
         @Override
@@ -271,8 +272,8 @@
         @Override
         public boolean equals(Object other) {
             if (other instanceof ActivityLaunchCancelled) {
-                return Objects.equals(activityRecordSnapshot,
-                        ((ActivityLaunchCancelled)other).activityRecordSnapshot) &&
+                return Arrays.equals(activityRecordSnapshot,
+                    ((ActivityLaunchCancelled)other).activityRecordSnapshot) &&
                         super.equals(other);
             }
             return false;
@@ -280,7 +281,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", " + activityRecordSnapshot.toString();
+            return super.toStringBody() + ", " + new String(activityRecordSnapshot);
         }
 
         @Override
@@ -325,7 +326,7 @@
 
         @Override
         protected String toStringBody() {
-            return ", timestampNs=" + Long.toString(timestampNs);
+            return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
         }
 
         @Override
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
new file mode 100644
index 0000000..51e407d
--- /dev/null
+++ b/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
@@ -0,0 +1,181 @@
+/*
+ * 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.google.android.startop.iorap
+
+import android.content.Intent;
+import android.net.Uri
+import android.os.Parcel
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import com.google.android.startop.iorap.AppLaunchEvent;
+import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunched
+import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchCancelled
+import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchFinished
+import com.google.android.startop.iorap.AppLaunchEvent.IntentStarted;
+import com.google.android.startop.iorap.AppLaunchEvent.IntentFailed;
+import com.google.android.startop.iorap.AppLaunchEvent.ReportFullyDrawn
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+
+/**
+ * Basic unit tests to test all of the [AppLaunchEvent]s in [com.google.android.startop.iorap].
+ */
+@SmallTest
+class AppLaunchEventTest {
+  /**
+   * Test for IntentStarted.
+   */
+  @Test
+  fun testIntentStarted() {
+    var intent = Intent()
+    val valid = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
+    val copy = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
+    val noneCopy1 = IntentStarted(/* sequenceId= */1L, intent, /* timestampNs= */ 1L)
+    val noneCopy2 = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 2L)
+    val noneCopy3 = IntentStarted(/* sequenceId= */2L, Intent(), /* timestampNs= */ 1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("IntentStarted{sequenceId=2, intent=Intent {  } , timestampNs=1}")
+  }
+
+  /**
+   * Test for IntentFailed.
+   */
+  @Test
+  fun testIntentFailed() {
+    val valid = IntentFailed(/* sequenceId= */2L)
+    val copy = IntentFailed(/* sequenceId= */2L)
+    val noneCopy = IntentFailed(/* sequenceId= */1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("IntentFailed{sequenceId=2}")
+  }
+
+  /**
+   * Test for ActivityLaunched.
+   */
+  @Test
+  fun testActivityLaunched() {
+    //var activityRecord =
+    val valid = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
+      /* temperature= */ 0)
+    val copy = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
+      /* temperature= */ 0)
+    val noneCopy1 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
+      /* temperature= */ 0)
+    val noneCopy2 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
+      /* temperature= */ 1)
+    val noneCopy3 = ActivityLaunched(/* sequenceId= */1L, "test1".toByteArray(),
+      /* temperature= */ 0)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ActivityLaunched{sequenceId=2, test, temperature=0}")
+  }
+
+
+  /**
+   * Test for ActivityLaunchFinished.
+   */
+  @Test
+  fun testActivityLaunchFinished() {
+    val valid = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val copy = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy1 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy2 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 2L)
+    val noneCopy3 = ActivityLaunchFinished(/* sequenceId= */2L, "test1".toByteArray(),
+      /* timestampNs= */ 1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ActivityLaunchFinished{sequenceId=2, test, timestampNs=1}")
+  }
+
+  /**
+   * Test for ActivityLaunchCancelled.
+   */
+  @Test
+  fun testActivityLaunchCancelled() {
+    val valid = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
+    val copy = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
+    val noneCopy1 = ActivityLaunchCancelled(/* sequenceId= */1L, "test".toByteArray())
+    val noneCopy2 = ActivityLaunchCancelled(/* sequenceId= */2L, "test1".toByteArray())
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ActivityLaunchCancelled{sequenceId=2, test}")
+  }
+
+  /**
+   * Test for ReportFullyDrawn.
+   */
+  @Test
+  fun testReportFullyDrawn() {
+    val valid = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
+    val copy = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
+    val noneCopy1 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy2 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
+      /* timestampNs= */ 1L)
+    val noneCopy3 = ReportFullyDrawn(/* sequenceId= */2L, "test1".toByteArray(),
+      /* timestampNs= */ 1L)
+
+    // equals(Object other)
+    assertThat(valid).isEqualTo(copy)
+    assertThat(valid).isNotEqualTo(noneCopy1)
+    assertThat(valid).isNotEqualTo(noneCopy2)
+    assertThat(valid).isNotEqualTo(noneCopy3)
+
+    // test toString()
+    val result = valid.toString()
+    assertThat(result).isEqualTo("ReportFullyDrawn{sequenceId=2, test, timestampNs=1}")
+  }
+}
diff --git a/startop/scripts/app_startup/app_startup_runner_test.py b/startop/scripts/app_startup/app_startup_runner_test.py
index 382f6f3..0c2bbea 100755
--- a/startop/scripts/app_startup/app_startup_runner_test.py
+++ b/startop/scripts/app_startup/app_startup_runner_test.py
@@ -92,7 +92,7 @@
   """
   d = {'compiler_filters': None, 'simulate': False, 'debug': False,
        'output': None, 'timeout': 10, 'loop_count': 1, 'inodes': None,
-       'trace_duration': None, 'compiler_type': asr.CompilerType.HOST}
+       'trace_duration': None, 'compiler_type': asr.CompilerType.DEVICE}
   d.update(kwargs)
   return d
 
diff --git a/startop/scripts/iorap/compiler_test.py b/startop/scripts/iorap/compiler_test.py
index d1f11c5..b8de701 100644
--- a/startop/scripts/iorap/compiler_test.py
+++ b/startop/scripts/iorap/compiler_test.py
@@ -30,7 +30,7 @@
 """
 import os
 
-import compiler_host as compiler
+import compiler_ri as compiler
 
 DIR = os.path.abspath(os.path.dirname(__file__))
 TEXTCACHE = os.path.join(DIR, 'test_fixtures/compiler/common_textcache')
diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace b/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace
index f731e73..59ff753 100644
--- a/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace
+++ b/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace
@@ -10,94 +10,94 @@
 #                                    ||| /     delay
 #           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION
 #              | |        |      |   ||||       |         |
-       <unknown>-27388 (-----) [004] .... 1920260.530929: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1461937 ofs=9535488
-       <unknown>-27388 (-----) [005] .... 1920260.532161: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1344589 ofs=9474048
-       <unknown>-27388 (-----) [005] .... 1920260.532183: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1153671 ofs=9478144
-       <unknown>-27388 (-----) [005] .... 1920260.532184: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1219563 ofs=9482240
-       <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1083162 ofs=9486336
-       <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1147318 ofs=9490432
-       <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1333594 ofs=9494528
-       <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1375715 ofs=9498624
-       <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1184831 ofs=9502720
-       <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1241653 ofs=9506816
-       <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1134975 ofs=9510912
-       <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1145772 ofs=9515008
-       <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1090457 ofs=9519104
-       <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1137942 ofs=9523200
-       <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1130123 ofs=9527296
-       <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1208783 ofs=9531392
-       <unknown>-27388 (-----) [005] .... 1920260.532192: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1294989 ofs=9539584
-       <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1163979 ofs=9543680
-       <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1350628 ofs=9547776
-       <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1386717 ofs=9551872
-       <unknown>-27388 (-----) [005] .... 1920260.532207: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1316148 ofs=9555968
-       <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1316419 ofs=9560064
-       <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1149076 ofs=9564160
-       <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1372772 ofs=9568256
-       <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1116389 ofs=9572352
-       <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1325458 ofs=9576448
-       <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1195423 ofs=9580544
-       <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1250964 ofs=9584640
-       <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1196027 ofs=9588736
-       <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1354059 ofs=9592832
-       <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1264649 ofs=9596928
-       <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1245285 ofs=9601024
-       <unknown>-27388 (-----) [005] .... 1920260.535119: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1411552 ofs=44244992
+       <unknown>-27388 (-----) [004] .... 1920260.530929: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1461937 ofs=9535488
+       <unknown>-27388 (-----) [005] .... 1920260.532161: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1344589 ofs=9474048
+       <unknown>-27388 (-----) [005] .... 1920260.532183: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1153671 ofs=9478144
+       <unknown>-27388 (-----) [005] .... 1920260.532184: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1219563 ofs=9482240
+       <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1083162 ofs=9486336
+       <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1147318 ofs=9490432
+       <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1333594 ofs=9494528
+       <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1375715 ofs=9498624
+       <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1184831 ofs=9502720
+       <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1241653 ofs=9506816
+       <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1134975 ofs=9510912
+       <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1145772 ofs=9515008
+       <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1090457 ofs=9519104
+       <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1137942 ofs=9523200
+       <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1130123 ofs=9527296
+       <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1208783 ofs=9531392
+       <unknown>-27388 (-----) [005] .... 1920260.532192: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1294989 ofs=9539584
+       <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1163979 ofs=9543680
+       <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1350628 ofs=9547776
+       <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1386717 ofs=9551872
+       <unknown>-27388 (-----) [005] .... 1920260.532207: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1316148 ofs=9555968
+       <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1316419 ofs=9560064
+       <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1149076 ofs=9564160
+       <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1372772 ofs=9568256
+       <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1116389 ofs=9572352
+       <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1325458 ofs=9576448
+       <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1195423 ofs=9580544
+       <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1250964 ofs=9584640
+       <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1196027 ofs=9588736
+       <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1354059 ofs=9592832
+       <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1264649 ofs=9596928
+       <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1245285 ofs=9601024
+       <unknown>-27388 (-----) [005] .... 1920260.535119: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1411552 ofs=44244992
        <unknown>-27388 (-----) [005] .... 1920260.535129: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1483081 ofs=433524736
        <unknown>-27388 (-----) [004] .... 1920260.536144: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1276173 ofs=438185984
-       <unknown>-27388 (-----) [004] .... 1920260.536462: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1174575 ofs=44249088
-       <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1126294 ofs=44253184
-       <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1248232 ofs=44257280
-       <unknown>-27388 (-----) [004] .... 1920260.537065: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1332993 ofs=44240896
-       <unknown>-27388 (-----) [006] .... 1920260.537646: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1153343 ofs=44400640
-       <unknown>-27388 (-----) [005] .... 1920260.538777: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1358397 ofs=44474368
-       <unknown>-12683 (-----) [006] .... 1920260.560094: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1426577 ofs=0
+       <unknown>-27388 (-----) [004] .... 1920260.536462: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1174575 ofs=44249088
+       <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1126294 ofs=44253184
+       <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1248232 ofs=44257280
+       <unknown>-27388 (-----) [004] .... 1920260.537065: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1332993 ofs=44240896
+       <unknown>-27388 (-----) [006] .... 1920260.537646: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1153343 ofs=44400640
+       <unknown>-27388 (-----) [005] .... 1920260.538777: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1358397 ofs=44474368
+       <unknown>-12683 (-----) [006] .... 1920260.560094: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1426577 ofs=0
        <unknown>-12683 (-----) [006] .... 1920260.560105: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117587 ofs=1171456
-       <unknown>-12683 (-----) [006] .... 1920260.561199: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099987 ofs=4096
-       <unknown>-12683 (-----) [006] .... 1920260.561411: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099910 ofs=16384
-       <unknown>-12683 (-----) [006] .... 1920260.561598: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099905 ofs=20480
-       <unknown>-12683 (-----) [006] .... 1920260.561758: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099883 ofs=32768
-       <unknown>-12683 (-----) [006] .... 1920260.562088: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099809 ofs=36864
-       <unknown>-12683 (-----) [006] .... 1920260.562325: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099803 ofs=98304
-       <unknown>-12683 (-----) [006] .... 1920260.562516: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099795 ofs=102400
-       <unknown>-12683 (-----) [006] .... 1920260.563094: mm_filemap_add_to_page_cache: dev 0:64768 ino 1523 page=0000000000000000 pfn=1107649 ofs=12288
-       <unknown>-12683 (-----) [006] .... 1920260.563105: mm_filemap_add_to_page_cache: dev 0:64768 ino 1523 page=0000000000000000 pfn=1269029 ofs=16384
-       <unknown>-12683 (-----) [006] .... 1920260.563785: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1451096 ofs=8192
-       <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1301480 ofs=12288
-       <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1314353 ofs=16384
-       <unknown>-12683 (-----) [006] .... 1920260.563791: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1216744 ofs=24576
-       <unknown>-12683 (-----) [006] .... 1920260.564309: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099787 ofs=49152
-       <unknown>-12683 (-----) [006] .... 1920260.564514: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099778 ofs=53248
-       <unknown>-12683 (-----) [005] .... 1920260.564756: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1148849 ofs=114688
-       <unknown>-12683 (-----) [005] .... 1920260.564973: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1164731 ofs=118784
-       <unknown>-12683 (-----) [005] .... 1920260.565000: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1170255 ofs=0
-       <unknown>-12683 (-----) [005] .... 1920260.565003: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1181043 ofs=4096
-       <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1296004 ofs=8192
-       <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1102004 ofs=12288
+       <unknown>-12683 (-----) [006] .... 1920260.561199: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099987 ofs=4096
+       <unknown>-12683 (-----) [006] .... 1920260.561411: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099910 ofs=16384
+       <unknown>-12683 (-----) [006] .... 1920260.561598: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099905 ofs=20480
+       <unknown>-12683 (-----) [006] .... 1920260.561758: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099883 ofs=32768
+       <unknown>-12683 (-----) [006] .... 1920260.562088: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099809 ofs=36864
+       <unknown>-12683 (-----) [006] .... 1920260.562325: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099803 ofs=98304
+       <unknown>-12683 (-----) [006] .... 1920260.562516: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099795 ofs=102400
+       <unknown>-12683 (-----) [006] .... 1920260.563094: mm_filemap_add_to_page_cache: dev 0:64768 ino 5f3 page=0000000000000000 pfn=1107649 ofs=12288
+       <unknown>-12683 (-----) [006] .... 1920260.563105: mm_filemap_add_to_page_cache: dev 0:64768 ino 5f3 page=0000000000000000 pfn=1269029 ofs=16384
+       <unknown>-12683 (-----) [006] .... 1920260.563785: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1451096 ofs=8192
+       <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1301480 ofs=12288
+       <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1314353 ofs=16384
+       <unknown>-12683 (-----) [006] .... 1920260.563791: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1216744 ofs=24576
+       <unknown>-12683 (-----) [006] .... 1920260.564309: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099787 ofs=49152
+       <unknown>-12683 (-----) [006] .... 1920260.564514: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099778 ofs=53248
+       <unknown>-12683 (-----) [005] .... 1920260.564756: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1148849 ofs=114688
+       <unknown>-12683 (-----) [005] .... 1920260.564973: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1164731 ofs=118784
+       <unknown>-12683 (-----) [005] .... 1920260.565000: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1170255 ofs=0
+       <unknown>-12683 (-----) [005] .... 1920260.565003: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1181043 ofs=4096
+       <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1296004 ofs=8192
+       <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1102004 ofs=12288
        <unknown>-12683 (-----) [005] .... 1920260.565626: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1351232 ofs=470597632
        <unknown>-12683 (-----) [005] .... 1920260.565982: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1391336 ofs=40210432
        <unknown>-12683 (-----) [005] .... 1920260.565985: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267536 ofs=12668928
-       <unknown>-27388 (-----) [007] .... 1920260.566082: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1256752 ofs=43921408
+       <unknown>-27388 (-----) [007] .... 1920260.566082: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1256752 ofs=43921408
        <unknown>-12683 (-----) [005] .... 1920260.566516: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1110966 ofs=176226304
        <unknown>-12683 (-----) [005] .... 1920260.566519: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1060586 ofs=12967936
        <unknown>-12683 (-----) [004] .... 1920260.567773: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117234 ofs=421888
        <unknown>-12683 (-----) [005] .... 1920260.568604: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1210571 ofs=430080
-       <unknown>-12683 (-----) [005] .... 1920260.568887: mm_filemap_add_to_page_cache: dev 0:64771 ino 105 page=0000000000000000 pfn=1055640 ofs=0
-       <unknown>-12683 (-----) [005] .... 1920260.568908: mm_filemap_add_to_page_cache: dev 0:64771 ino 73 page=0000000000000000 pfn=1142694 ofs=0
+       <unknown>-12683 (-----) [005] .... 1920260.568887: mm_filemap_add_to_page_cache: dev 0:64771 ino 69 page=0000000000000000 pfn=1055640 ofs=0
+       <unknown>-12683 (-----) [005] .... 1920260.568908: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1142694 ofs=0
        <unknown>-12683 (-----) [005] .... 1920260.568910: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1060788 ofs=299008
-       <unknown>-12683 (-----) [005] .... 1920260.569418: mm_filemap_add_to_page_cache: dev 0:64771 ino 73 page=0000000000000000 pfn=1085046 ofs=4096
-       <unknown>-12683 (-----) [005] .... 1920260.569640: mm_filemap_add_to_page_cache: dev 0:64771 ino 73 page=0000000000000000 pfn=1057135 ofs=8192
+       <unknown>-12683 (-----) [005] .... 1920260.569418: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1085046 ofs=4096
+       <unknown>-12683 (-----) [005] .... 1920260.569640: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1057135 ofs=8192
        <unknown>-12683 (-----) [005] .... 1920260.569833: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1058976 ofs=19406848
        <unknown>-12683 (-----) [005] .... 1920260.569835: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1477947 ofs=10526720
-       <unknown>-12683 (-----) [005] .... 1920260.572285: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1237492 ofs=299008
-       <unknown>-12683 (-----) [005] .... 1920260.572297: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1264914 ofs=339968
-       <unknown>-12683 (-----) [005] .... 1920260.572314: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1434748 ofs=348160
-       <unknown>-12683 (-----) [005] .... 1920260.572316: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1372959 ofs=352256
-       <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1258955 ofs=356352
-       <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1113420 ofs=360448
-       <unknown>-12683 (-----) [005] .... 1920260.572318: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1137083 ofs=364544
-       <unknown>-12683 (-----) [004] .... 1920260.575490: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1379679 ofs=65536
-       <unknown>-12683 (-----) [006] .... 1920260.576194: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1323898 ofs=69632
+       <unknown>-12683 (-----) [005] .... 1920260.572285: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1237492 ofs=299008
+       <unknown>-12683 (-----) [005] .... 1920260.572297: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1264914 ofs=339968
+       <unknown>-12683 (-----) [005] .... 1920260.572314: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1434748 ofs=348160
+       <unknown>-12683 (-----) [005] .... 1920260.572316: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1372959 ofs=352256
+       <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1258955 ofs=356352
+       <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1113420 ofs=360448
+       <unknown>-12683 (-----) [005] .... 1920260.572318: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1137083 ofs=364544
+       <unknown>-12683 (-----) [004] .... 1920260.575490: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1379679 ofs=65536
+       <unknown>-12683 (-----) [006] .... 1920260.576194: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1323898 ofs=69632
        <unknown>-12683 (-----) [006] .... 1920260.576248: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323895 ofs=262623232
        <unknown>-12683 (-----) [006] .... 1920260.576251: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323861 ofs=13156352
        <unknown>-12683 (-----) [005] .... 1920260.576810: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1477585 ofs=262590464
@@ -105,644 +105,644 @@
        <unknown>-12683 (-----) [004] .... 1920260.577200: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267618 ofs=12636160
        <unknown>-12683 (-----) [005] .... 1920260.577725: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1056225 ofs=228618240
        <unknown>-12683 (-----) [005] .... 1920260.577727: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1164942 ofs=13082624
-       <unknown>-12683 (-----) [007] .... 1920260.578411: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1372616 ofs=0
-       <unknown>-12683 (-----) [007] .... 1920260.578422: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1307468 ofs=4096
-       <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1120117 ofs=8192
-       <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1217989 ofs=12288
-       <unknown>-12683 (-----) [007] .... 1920260.578650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1475011 ofs=5419008
+       <unknown>-12683 (-----) [007] .... 1920260.578411: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1372616 ofs=0
+       <unknown>-12683 (-----) [007] .... 1920260.578422: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1307468 ofs=4096
+       <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1120117 ofs=8192
+       <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1217989 ofs=12288
+       <unknown>-12683 (-----) [007] .... 1920260.578650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1475011 ofs=5419008
        <unknown>-12683 (-----) [007] .... 1920260.578653: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1066084 ofs=236453888
        <unknown>-12683 (-----) [007] .... 1920260.578654: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1100271 ofs=13099008
-       <unknown>-12683 (-----) [004] .... 1920260.579004: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1485156 ofs=5423104
-       <unknown>-12683 (-----) [004] .... 1920260.579005: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1124212 ofs=5427200
-       <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1195377 ofs=5431296
-       <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1265888 ofs=5435392
-       <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1170194 ofs=5439488
-       <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1403742 ofs=5443584
-       <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1123826 ofs=5447680
-       <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1255034 ofs=5451776
-       <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1190447 ofs=5455872
-       <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1286864 ofs=5459968
-       <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1428535 ofs=5464064
-       <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1184092 ofs=5468160
-       <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1411906 ofs=5472256
-       <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1342349 ofs=5476352
-       <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1188185 ofs=5480448
-       <unknown>-12683 (-----) [004] .... 1920260.579014: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1158702 ofs=5484544
-       <unknown>-12683 (-----) [005] .... 1920260.579430: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1299421 ofs=5230592
-       <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1317097 ofs=5234688
-       <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1441714 ofs=5238784
-       <unknown>-12683 (-----) [005] .... 1920260.579438: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1081974 ofs=5242880
-       <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1128684 ofs=5246976
-       <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447381 ofs=5251072
-       <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1466410 ofs=5255168
-       <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1259909 ofs=5259264
-       <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1125784 ofs=5263360
-       <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1270592 ofs=5267456
-       <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1246070 ofs=5271552
-       <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1472544 ofs=5275648
-       <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1113357 ofs=5279744
-       <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1202021 ofs=5283840
-       <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1078639 ofs=5287936
-       <unknown>-12683 (-----) [005] .... 1920260.579449: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1176171 ofs=5292032
-       <unknown>-12683 (-----) [005] .... 1920260.579450: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1089516 ofs=5296128
-       <unknown>-12683 (-----) [005] .... 1920260.579451: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1400065 ofs=5300224
-       <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1300489 ofs=5304320
-       <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1452081 ofs=5308416
-       <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1161862 ofs=5312512
-       <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1161871 ofs=5316608
-       <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1263798 ofs=5320704
-       <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1126887 ofs=5324800
-       <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1375498 ofs=5328896
-       <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1328067 ofs=5332992
-       <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1420691 ofs=5337088
-       <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1298707 ofs=5341184
-       <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1078670 ofs=5345280
-       <unknown>-12683 (-----) [005] .... 1920260.579457: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1430498 ofs=5349376
-       <unknown>-12683 (-----) [005] .... 1920260.579458: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1338720 ofs=5353472
-       <unknown>-12683 (-----) [005] .... 1920260.579476: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1452611 ofs=5357568
-       <unknown>-12683 (-----) [006] .... 1920260.580451: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1241967 ofs=0
-       <unknown>-12683 (-----) [006] .... 1920260.580454: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1116541 ofs=4096
-       <unknown>-12683 (-----) [006] .... 1920260.580461: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1145049 ofs=8192
-       <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1277255 ofs=12288
-       <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1098037 ofs=16384
-       <unknown>-12683 (-----) [006] .... 1920260.580463: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1135986 ofs=20480
-       <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1154455 ofs=24576
-       <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1221822 ofs=28672
-       <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1078684 ofs=32768
-       <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1158876 ofs=36864
-       <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1289644 ofs=40960
-       <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1289386 ofs=45056
-       <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1131002 ofs=49152
-       <unknown>-12683 (-----) [006] .... 1920260.580467: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1464335 ofs=53248
-       <unknown>-12683 (-----) [006] .... 1920260.580468: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1135789 ofs=57344
-       <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1240897 ofs=61440
-       <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1241770 ofs=65536
-       <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1421959 ofs=69632
-       <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1230007 ofs=73728
-       <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1109271 ofs=77824
-       <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1159974 ofs=81920
-       <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1154528 ofs=86016
-       <unknown>-12683 (-----) [006] .... 1920260.580472: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1315790 ofs=90112
-       <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1185583 ofs=94208
-       <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1253153 ofs=98304
-       <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103982 ofs=102400
-       <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1284589 ofs=106496
-       <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1169601 ofs=110592
-       <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1206248 ofs=114688
-       <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1261161 ofs=118784
-       <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1305841 ofs=122880
-       <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1468293 ofs=126976
-       <unknown>-12683 (-----) [004] .... 1920260.580646: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1318816 ofs=16384
-       <unknown>-12683 (-----) [004] .... 1920260.580649: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1472922 ofs=20480
-       <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1473229 ofs=24576
-       <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1524262 ofs=28672
-       <unknown>-12683 (-----) [004] .... 1920260.580656: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1205714 ofs=32768
-       <unknown>-12683 (-----) [004] .... 1920260.580657: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1310560 ofs=36864
-       <unknown>-12683 (-----) [004] .... 1920260.580658: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1295070 ofs=40960
-       <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1404093 ofs=45056
-       <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1435814 ofs=49152
-       <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1435442 ofs=53248
-       <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1096077 ofs=57344
-       <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1483793 ofs=61440
-       <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1231298 ofs=65536
-       <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1215648 ofs=69632
-       <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1327326 ofs=73728
-       <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1108894 ofs=77824
-       <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1327545 ofs=81920
-       <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1328804 ofs=86016
-       <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1300171 ofs=90112
-       <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1353250 ofs=94208
-       <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1333681 ofs=98304
-       <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1144969 ofs=102400
-       <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1450962 ofs=106496
-       <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1255701 ofs=110592
-       <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1294782 ofs=114688
-       <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1226912 ofs=118784
-       <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1294579 ofs=122880
-       <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1246960 ofs=126976
-       <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1199086 ofs=131072
-       <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1449590 ofs=135168
-       <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1276363 ofs=139264
-       <unknown>-12683 (-----) [004] .... 1920260.580675: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1389998 ofs=143360
-       <unknown>-12683 (-----) [004] .... 1920260.580739: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1423031 ofs=1249280
-       <unknown>-12683 (-----) [004] .... 1920260.580741: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1171032 ofs=1253376
-       <unknown>-12683 (-----) [004] .... 1920260.580742: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1320946 ofs=1257472
-       <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1314696 ofs=1261568
-       <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1414864 ofs=1265664
-       <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1334933 ofs=1269760
-       <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1242845 ofs=1273856
-       <unknown>-12683 (-----) [004] .... 1920260.580747: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1289488 ofs=1277952
-       <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1335445 ofs=1282048
-       <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1289663 ofs=1286144
-       <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1080462 ofs=1290240
-       <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1286303 ofs=1294336
-       <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1353531 ofs=1298432
-       <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1280701 ofs=1302528
-       <unknown>-12683 (-----) [004] .... 1920260.580751: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1107730 ofs=1306624
-       <unknown>-12683 (-----) [004] .... 1920260.580752: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1242729 ofs=1310720
-       <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1078336 ofs=1314816
-       <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1372425 ofs=1318912
-       <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1248813 ofs=1323008
-       <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1201155 ofs=1327104
-       <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1250103 ofs=1331200
-       <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1359710 ofs=1335296
-       <unknown>-12683 (-----) [004] .... 1920260.580756: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1272462 ofs=1339392
-       <unknown>-12683 (-----) [004] .... 1920260.580758: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1097035 ofs=1343488
-       <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1233124 ofs=1347584
-       <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1455812 ofs=1351680
-       <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1355689 ofs=1355776
-       <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1263593 ofs=1359872
-       <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1230789 ofs=1363968
-       <unknown>-12683 (-----) [004] .... 1920260.580761: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1143766 ofs=1368064
-       <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1269666 ofs=1372160
-       <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1353022 ofs=1376256
-       <unknown>-12683 (-----) [004] .... 1920260.581613: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1355509 ofs=258048
-       <unknown>-12683 (-----) [004] .... 1920260.581615: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1178902 ofs=262144
-       <unknown>-12683 (-----) [004] .... 1920260.581616: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1193649 ofs=266240
-       <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1225497 ofs=270336
-       <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1228259 ofs=274432
-       <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1309674 ofs=278528
-       <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1239390 ofs=282624
-       <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1468083 ofs=286720
-       <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1292751 ofs=290816
-       <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1318066 ofs=294912
-       <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1489314 ofs=299008
-       <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1169867 ofs=303104
-       <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1314256 ofs=307200
-       <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1310230 ofs=311296
-       <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1356180 ofs=315392
-       <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1419179 ofs=319488
-       <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1307265 ofs=323584
-       <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1218590 ofs=327680
-       <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447586 ofs=331776
-       <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1209382 ofs=335872
-       <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1072148 ofs=339968
-       <unknown>-12683 (-----) [004] .... 1920260.581645: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1227195 ofs=344064
-       <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1246369 ofs=348160
-       <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1193845 ofs=352256
-       <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1137553 ofs=356352
-       <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1475215 ofs=360448
-       <unknown>-12683 (-----) [004] .... 1920260.581648: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1258935 ofs=364544
-       <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1448788 ofs=368640
-       <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447611 ofs=372736
-       <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1290842 ofs=376832
-       <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447826 ofs=380928
-       <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1181016 ofs=385024
-       <unknown>-12683 (-----) [005] .... 1920260.582230: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1216810 ofs=1662976
-       <unknown>-12683 (-----) [005] .... 1920260.582234: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1175966 ofs=1667072
-       <unknown>-12683 (-----) [005] .... 1920260.582235: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1449798 ofs=1671168
-       <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1273480 ofs=1675264
-       <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1152779 ofs=1679360
-       <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1272810 ofs=1683456
-       <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1248634 ofs=1687552
-       <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1203376 ofs=1691648
-       <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1138880 ofs=1695744
-       <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1344591 ofs=1699840
-       <unknown>-12683 (-----) [005] .... 1920260.582239: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1416060 ofs=1703936
-       <unknown>-12683 (-----) [005] .... 1920260.582246: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1128676 ofs=1708032
-       <unknown>-12683 (-----) [005] .... 1920260.582247: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1301921 ofs=1712128
-       <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1384569 ofs=1716224
-       <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1249106 ofs=1720320
-       <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1206596 ofs=1724416
-       <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1429831 ofs=1728512
-       <unknown>-12683 (-----) [005] .... 1920260.582252: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1107796 ofs=1732608
-       <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1098336 ofs=1736704
-       <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1230286 ofs=1740800
-       <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1100370 ofs=1744896
-       <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1241930 ofs=1748992
-       <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1366807 ofs=1753088
-       <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1136252 ofs=1757184
-       <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1274291 ofs=1761280
-       <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1254775 ofs=1765376
-       <unknown>-12683 (-----) [005] .... 1920260.582259: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1194679 ofs=1769472
-       <unknown>-12683 (-----) [005] .... 1920260.582262: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1177090 ofs=1773568
-       <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1343925 ofs=1777664
-       <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1159217 ofs=1781760
-       <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1435471 ofs=1785856
-       <unknown>-12683 (-----) [005] .... 1920260.582264: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1435529 ofs=1789952
-       <unknown>-12683 (-----) [004] .... 1920260.582524: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1181910 ofs=0
-       <unknown>-12683 (-----) [004] .... 1920260.582528: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1212021 ofs=4096
-       <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1162778 ofs=8192
-       <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1107700 ofs=12288
-       <unknown>-12683 (-----) [004] .... 1920260.583553: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1093394 ofs=3399680
+       <unknown>-12683 (-----) [004] .... 1920260.579004: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1485156 ofs=5423104
+       <unknown>-12683 (-----) [004] .... 1920260.579005: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1124212 ofs=5427200
+       <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1195377 ofs=5431296
+       <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1265888 ofs=5435392
+       <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1170194 ofs=5439488
+       <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1403742 ofs=5443584
+       <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1123826 ofs=5447680
+       <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1255034 ofs=5451776
+       <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1190447 ofs=5455872
+       <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1286864 ofs=5459968
+       <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1428535 ofs=5464064
+       <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1184092 ofs=5468160
+       <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1411906 ofs=5472256
+       <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1342349 ofs=5476352
+       <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1188185 ofs=5480448
+       <unknown>-12683 (-----) [004] .... 1920260.579014: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1158702 ofs=5484544
+       <unknown>-12683 (-----) [005] .... 1920260.579430: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1299421 ofs=5230592
+       <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1317097 ofs=5234688
+       <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1441714 ofs=5238784
+       <unknown>-12683 (-----) [005] .... 1920260.579438: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1081974 ofs=5242880
+       <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1128684 ofs=5246976
+       <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447381 ofs=5251072
+       <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1466410 ofs=5255168
+       <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1259909 ofs=5259264
+       <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1125784 ofs=5263360
+       <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1270592 ofs=5267456
+       <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246070 ofs=5271552
+       <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1472544 ofs=5275648
+       <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1113357 ofs=5279744
+       <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1202021 ofs=5283840
+       <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078639 ofs=5287936
+       <unknown>-12683 (-----) [005] .... 1920260.579449: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1176171 ofs=5292032
+       <unknown>-12683 (-----) [005] .... 1920260.579450: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1089516 ofs=5296128
+       <unknown>-12683 (-----) [005] .... 1920260.579451: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1400065 ofs=5300224
+       <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1300489 ofs=5304320
+       <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1452081 ofs=5308416
+       <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1161862 ofs=5312512
+       <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1161871 ofs=5316608
+       <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1263798 ofs=5320704
+       <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1126887 ofs=5324800
+       <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1375498 ofs=5328896
+       <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1328067 ofs=5332992
+       <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1420691 ofs=5337088
+       <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1298707 ofs=5341184
+       <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078670 ofs=5345280
+       <unknown>-12683 (-----) [005] .... 1920260.579457: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1430498 ofs=5349376
+       <unknown>-12683 (-----) [005] .... 1920260.579458: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1338720 ofs=5353472
+       <unknown>-12683 (-----) [005] .... 1920260.579476: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1452611 ofs=5357568
+       <unknown>-12683 (-----) [006] .... 1920260.580451: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241967 ofs=0
+       <unknown>-12683 (-----) [006] .... 1920260.580454: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1116541 ofs=4096
+       <unknown>-12683 (-----) [006] .... 1920260.580461: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1145049 ofs=8192
+       <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1277255 ofs=12288
+       <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1098037 ofs=16384
+       <unknown>-12683 (-----) [006] .... 1920260.580463: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1135986 ofs=20480
+       <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1154455 ofs=24576
+       <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1221822 ofs=28672
+       <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1078684 ofs=32768
+       <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1158876 ofs=36864
+       <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1289644 ofs=40960
+       <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1289386 ofs=45056
+       <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1131002 ofs=49152
+       <unknown>-12683 (-----) [006] .... 1920260.580467: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1464335 ofs=53248
+       <unknown>-12683 (-----) [006] .... 1920260.580468: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1135789 ofs=57344
+       <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1240897 ofs=61440
+       <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241770 ofs=65536
+       <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1421959 ofs=69632
+       <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1230007 ofs=73728
+       <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1109271 ofs=77824
+       <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1159974 ofs=81920
+       <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1154528 ofs=86016
+       <unknown>-12683 (-----) [006] .... 1920260.580472: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1315790 ofs=90112
+       <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1185583 ofs=94208
+       <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1253153 ofs=98304
+       <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103982 ofs=102400
+       <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1284589 ofs=106496
+       <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1169601 ofs=110592
+       <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1206248 ofs=114688
+       <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1261161 ofs=118784
+       <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1305841 ofs=122880
+       <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1468293 ofs=126976
+       <unknown>-12683 (-----) [004] .... 1920260.580646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1318816 ofs=16384
+       <unknown>-12683 (-----) [004] .... 1920260.580649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1472922 ofs=20480
+       <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1473229 ofs=24576
+       <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1524262 ofs=28672
+       <unknown>-12683 (-----) [004] .... 1920260.580656: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1205714 ofs=32768
+       <unknown>-12683 (-----) [004] .... 1920260.580657: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1310560 ofs=36864
+       <unknown>-12683 (-----) [004] .... 1920260.580658: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1295070 ofs=40960
+       <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1404093 ofs=45056
+       <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1435814 ofs=49152
+       <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1435442 ofs=53248
+       <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1096077 ofs=57344
+       <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1483793 ofs=61440
+       <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1231298 ofs=65536
+       <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1215648 ofs=69632
+       <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1327326 ofs=73728
+       <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1108894 ofs=77824
+       <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1327545 ofs=81920
+       <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1328804 ofs=86016
+       <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1300171 ofs=90112
+       <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353250 ofs=94208
+       <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1333681 ofs=98304
+       <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1144969 ofs=102400
+       <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1450962 ofs=106496
+       <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1255701 ofs=110592
+       <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1294782 ofs=114688
+       <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1226912 ofs=118784
+       <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1294579 ofs=122880
+       <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246960 ofs=126976
+       <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1199086 ofs=131072
+       <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1449590 ofs=135168
+       <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1276363 ofs=139264
+       <unknown>-12683 (-----) [004] .... 1920260.580675: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1389998 ofs=143360
+       <unknown>-12683 (-----) [004] .... 1920260.580739: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1423031 ofs=1249280
+       <unknown>-12683 (-----) [004] .... 1920260.580741: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1171032 ofs=1253376
+       <unknown>-12683 (-----) [004] .... 1920260.580742: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1320946 ofs=1257472
+       <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1314696 ofs=1261568
+       <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1414864 ofs=1265664
+       <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1334933 ofs=1269760
+       <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1242845 ofs=1273856
+       <unknown>-12683 (-----) [004] .... 1920260.580747: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1289488 ofs=1277952
+       <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1335445 ofs=1282048
+       <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1289663 ofs=1286144
+       <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1080462 ofs=1290240
+       <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1286303 ofs=1294336
+       <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353531 ofs=1298432
+       <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1280701 ofs=1302528
+       <unknown>-12683 (-----) [004] .... 1920260.580751: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1107730 ofs=1306624
+       <unknown>-12683 (-----) [004] .... 1920260.580752: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1242729 ofs=1310720
+       <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078336 ofs=1314816
+       <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1372425 ofs=1318912
+       <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1248813 ofs=1323008
+       <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1201155 ofs=1327104
+       <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1250103 ofs=1331200
+       <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1359710 ofs=1335296
+       <unknown>-12683 (-----) [004] .... 1920260.580756: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1272462 ofs=1339392
+       <unknown>-12683 (-----) [004] .... 1920260.580758: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1097035 ofs=1343488
+       <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1233124 ofs=1347584
+       <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1455812 ofs=1351680
+       <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1355689 ofs=1355776
+       <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1263593 ofs=1359872
+       <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1230789 ofs=1363968
+       <unknown>-12683 (-----) [004] .... 1920260.580761: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1143766 ofs=1368064
+       <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1269666 ofs=1372160
+       <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353022 ofs=1376256
+       <unknown>-12683 (-----) [004] .... 1920260.581613: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1355509 ofs=258048
+       <unknown>-12683 (-----) [004] .... 1920260.581615: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1178902 ofs=262144
+       <unknown>-12683 (-----) [004] .... 1920260.581616: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1193649 ofs=266240
+       <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1225497 ofs=270336
+       <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1228259 ofs=274432
+       <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1309674 ofs=278528
+       <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1239390 ofs=282624
+       <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1468083 ofs=286720
+       <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1292751 ofs=290816
+       <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1318066 ofs=294912
+       <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1489314 ofs=299008
+       <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1169867 ofs=303104
+       <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1314256 ofs=307200
+       <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1310230 ofs=311296
+       <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1356180 ofs=315392
+       <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1419179 ofs=319488
+       <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1307265 ofs=323584
+       <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1218590 ofs=327680
+       <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447586 ofs=331776
+       <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1209382 ofs=335872
+       <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1072148 ofs=339968
+       <unknown>-12683 (-----) [004] .... 1920260.581645: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1227195 ofs=344064
+       <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246369 ofs=348160
+       <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1193845 ofs=352256
+       <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1137553 ofs=356352
+       <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1475215 ofs=360448
+       <unknown>-12683 (-----) [004] .... 1920260.581648: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1258935 ofs=364544
+       <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1448788 ofs=368640
+       <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447611 ofs=372736
+       <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1290842 ofs=376832
+       <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447826 ofs=380928
+       <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1181016 ofs=385024
+       <unknown>-12683 (-----) [005] .... 1920260.582230: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1216810 ofs=1662976
+       <unknown>-12683 (-----) [005] .... 1920260.582234: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1175966 ofs=1667072
+       <unknown>-12683 (-----) [005] .... 1920260.582235: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1449798 ofs=1671168
+       <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1273480 ofs=1675264
+       <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1152779 ofs=1679360
+       <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1272810 ofs=1683456
+       <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1248634 ofs=1687552
+       <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1203376 ofs=1691648
+       <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1138880 ofs=1695744
+       <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1344591 ofs=1699840
+       <unknown>-12683 (-----) [005] .... 1920260.582239: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1416060 ofs=1703936
+       <unknown>-12683 (-----) [005] .... 1920260.582246: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1128676 ofs=1708032
+       <unknown>-12683 (-----) [005] .... 1920260.582247: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1301921 ofs=1712128
+       <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1384569 ofs=1716224
+       <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1249106 ofs=1720320
+       <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1206596 ofs=1724416
+       <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1429831 ofs=1728512
+       <unknown>-12683 (-----) [005] .... 1920260.582252: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1107796 ofs=1732608
+       <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1098336 ofs=1736704
+       <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1230286 ofs=1740800
+       <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1100370 ofs=1744896
+       <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241930 ofs=1748992
+       <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1366807 ofs=1753088
+       <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1136252 ofs=1757184
+       <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1274291 ofs=1761280
+       <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1254775 ofs=1765376
+       <unknown>-12683 (-----) [005] .... 1920260.582259: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1194679 ofs=1769472
+       <unknown>-12683 (-----) [005] .... 1920260.582262: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1177090 ofs=1773568
+       <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1343925 ofs=1777664
+       <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1159217 ofs=1781760
+       <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435471 ofs=1785856
+       <unknown>-12683 (-----) [005] .... 1920260.582264: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435529 ofs=1789952
+       <unknown>-12683 (-----) [004] .... 1920260.582524: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1181910 ofs=0
+       <unknown>-12683 (-----) [004] .... 1920260.582528: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1212021 ofs=4096
+       <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1162778 ofs=8192
+       <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1107700 ofs=12288
+       <unknown>-12683 (-----) [004] .... 1920260.583553: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1093394 ofs=3399680
        <unknown>-12683 (-----) [004] .... 1920260.583984: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1121431 ofs=242503680
        <unknown>-12683 (-----) [004] .... 1920260.583986: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1168551 ofs=13115392
-       <unknown>-12683 (-----) [004] .... 1920260.584304: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1347409 ofs=0
-       <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1428681 ofs=4096
-       <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1259106 ofs=8192
-       <unknown>-12683 (-----) [004] .... 1920260.584308: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1343229 ofs=12288
-       <unknown>-12694 (-----) [005] .... 1920260.584622: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1098733 ofs=1531904
-       <unknown>-12696 (-----) [006] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331319 ofs=1536000
-       <unknown>-12694 (-----) [005] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1278537 ofs=1540096
-       <unknown>-12696 (-----) [006] .... 1920260.584631: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1492534 ofs=1544192
-       <unknown>-12694 (-----) [005] .... 1920260.584636: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1460878 ofs=1548288
-       <unknown>-12694 (-----) [005] .... 1920260.584640: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092973 ofs=1552384
-       <unknown>-12694 (-----) [005] .... 1920260.584641: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1103200 ofs=1556480
-       <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1257426 ofs=1560576
-       <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1219424 ofs=1564672
-       <unknown>-12683 (-----) [004] .... 1920260.584660: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1279352 ofs=1568768
-       <unknown>-12696 (-----) [006] .... 1920260.584662: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1260572 ofs=1572864
-       <unknown>-12683 (-----) [004] .... 1920260.584663: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1225809 ofs=1576960
-       <unknown>-12696 (-----) [006] .... 1920260.584665: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1350766 ofs=1585152
-       <unknown>-12697 (-----) [007] .... 1920260.584666: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1107173 ofs=1581056
-       <unknown>-12683 (-----) [004] .... 1920260.584668: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1305885 ofs=1589248
-       <unknown>-12694 (-----) [005] .... 1920260.584669: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1293385 ofs=1593344
-       <unknown>-12696 (-----) [006] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1173841 ofs=1597440
-       <unknown>-12697 (-----) [007] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1080021 ofs=1601536
-       <unknown>-12683 (-----) [004] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1147419 ofs=1605632
-       <unknown>-12696 (-----) [006] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1252762 ofs=1609728
-       <unknown>-12694 (-----) [005] .... 1920260.584674: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1323916 ofs=1613824
-       <unknown>-12683 (-----) [004] .... 1920260.584675: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1155631 ofs=1617920
-       <unknown>-12696 (-----) [006] .... 1920260.584676: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449815 ofs=1622016
-       <unknown>-12694 (-----) [005] .... 1920260.584678: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1227069 ofs=1626112
-       <unknown>-12696 (-----) [006] .... 1920260.584680: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1317692 ofs=1630208
-       <unknown>-12694 (-----) [005] .... 1920260.584681: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1492244 ofs=1634304
-       <unknown>-12683 (-----) [004] .... 1920260.584682: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241876 ofs=1638400
-       <unknown>-12697 (-----) [007] .... 1920260.585446: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1402958 ofs=167936
-       <unknown>-12697 (-----) [007] .... 1920260.585449: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1133263 ofs=172032
-       <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1295502 ofs=176128
-       <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1249495 ofs=180224
-       <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1237999 ofs=184320
-       <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1280965 ofs=188416
-       <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1208361 ofs=192512
-       <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1308840 ofs=196608
-       <unknown>-12695 (-----) [004] .... 1920260.585455: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1138875 ofs=569344
-       <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1314886 ofs=573440
-       <unknown>-12697 (-----) [007] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242734 ofs=200704
-       <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1447386 ofs=577536
-       <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241302 ofs=204800
-       <unknown>-12695 (-----) [004] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1328663 ofs=581632
-       <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1476101 ofs=208896
-       <unknown>-12695 (-----) [004] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1209461 ofs=585728
-       <unknown>-12697 (-----) [007] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1080147 ofs=212992
-       <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1128509 ofs=217088
-       <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1371915 ofs=221184
-       <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1264015 ofs=225280
-       <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1211695 ofs=229376
-       <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1150386 ofs=233472
-       <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1135747 ofs=237568
-       <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1128230 ofs=241664
-       <unknown>-12697 (-----) [007] .... 1920260.585464: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1155451 ofs=245760
-       <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1246841 ofs=249856
-       <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1462971 ofs=253952
-       <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1131333 ofs=258048
-       <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289407 ofs=262144
-       <unknown>-12695 (-----) [004] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1134730 ofs=589824
-       <unknown>-12697 (-----) [007] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289873 ofs=266240
-       <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1448734 ofs=270336
-       <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1129776 ofs=593920
-       <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1524090 ofs=274432
-       <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1399725 ofs=598016
-       <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1524081 ofs=278528
-       <unknown>-12695 (-----) [004] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1276535 ofs=602112
-       <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1524060 ofs=282624
-       <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449847 ofs=606208
-       <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1158944 ofs=286720
-       <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1384536 ofs=610304
-       <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1116785 ofs=290816
-       <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1308118 ofs=614400
-       <unknown>-12697 (-----) [007] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1448669 ofs=294912
-       <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1227050 ofs=618496
-       <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289324 ofs=622592
-       <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1187869 ofs=626688
-       <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1400523 ofs=630784
-       <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1344176 ofs=634880
-       <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092871 ofs=638976
-       <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092021 ofs=643072
-       <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1198169 ofs=647168
-       <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1371540 ofs=651264
-       <unknown>-12683 (-----) [005] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1195003 ofs=348160
-       <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1228787 ofs=655360
-       <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1236123 ofs=659456
-       <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1137213 ofs=663552
-       <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1294618 ofs=667648
-       <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241048 ofs=671744
-       <unknown>-12695 (-----) [004] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1228779 ofs=675840
-       <unknown>-12683 (-----) [005] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1199292 ofs=352256
-       <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1200861 ofs=356352
-       <unknown>-12695 (-----) [004] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1309572 ofs=679936
-       <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1215770 ofs=360448
-       <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1409002 ofs=684032
-       <unknown>-12683 (-----) [005] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1151883 ofs=364544
-       <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1103729 ofs=688128
-       <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1468126 ofs=368640
-       <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1162720 ofs=692224
-       <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1251672 ofs=372736
-       <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1199221 ofs=696320
-       <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1283325 ofs=376832
-       <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1190489 ofs=380928
-       <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1489117 ofs=385024
-       <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1273899 ofs=389120
-       <unknown>-12683 (-----) [005] .... 1920260.585485: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1274459 ofs=393216
-       <unknown>-12683 (-----) [005] .... 1920260.585486: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1316649 ofs=397312
-       <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1375678 ofs=401408
-       <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1483317 ofs=405504
-       <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1240286 ofs=409600
-       <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1131345 ofs=413696
-       <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1200483 ofs=417792
-       <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1384693 ofs=421888
-       <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1161385 ofs=425984
-       <unknown>-12683 (-----) [005] .... 1920260.585494: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1452025 ofs=430080
-       <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1253654 ofs=434176
-       <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1116697 ofs=438272
-       <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1432645 ofs=442368
-       <unknown>-12694 (-----) [006] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1337397 ofs=16384
-       <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1304229 ofs=446464
-       <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1419147 ofs=450560
-       <unknown>-12683 (-----) [005] .... 1920260.585498: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1349246 ofs=454656
-       <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1128519 ofs=458752
-       <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1125168 ofs=462848
-       <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1081031 ofs=20480
-       <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1293022 ofs=24576
-       <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1113007 ofs=28672
-       <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1339312 ofs=32768
-       <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1412311 ofs=36864
-       <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1260960 ofs=40960
-       <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189529 ofs=45056
-       <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1412184 ofs=49152
-       <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1481227 ofs=53248
-       <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1455940 ofs=57344
-       <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1299132 ofs=61440
-       <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1337375 ofs=65536
-       <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1328742 ofs=69632
-       <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1315646 ofs=73728
-       <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1225475 ofs=77824
-       <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1146097 ofs=81920
-       <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1318775 ofs=86016
-       <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1448391 ofs=90112
-       <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1441412 ofs=94208
-       <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1138111 ofs=98304
-       <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1143223 ofs=102400
-       <unknown>-12683 (-----) [005] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1079876 ofs=466944
-       <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1447637 ofs=106496
-       <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1220585 ofs=110592
-       <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449051 ofs=114688
-       <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1313180 ofs=118784
-       <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1313166 ofs=122880
-       <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1313154 ofs=126976
-       <unknown>-12683 (-----) [005] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1218394 ofs=471040
-       <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1144047 ofs=131072
-       <unknown>-12683 (-----) [005] .... 1920260.585537: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1218579 ofs=475136
-       <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241332 ofs=135168
-       <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1097199 ofs=139264
-       <unknown>-12694 (-----) [006] .... 1920260.585545: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1214197 ofs=143360
-       <unknown>-12694 (-----) [006] .... 1920260.585645: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1197633 ofs=147456
-       <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1311536 ofs=151552
-       <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1322952 ofs=155648
-       <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1346974 ofs=159744
-       <unknown>-12694 (-----) [006] .... 1920260.585648: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1257232 ofs=163840
-       <unknown>-12695 (-----) [004] .... 1920260.586355: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1204484 ofs=700416
-       <unknown>-12695 (-----) [004] .... 1920260.586357: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1326426 ofs=704512
-       <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1151808 ofs=708608
-       <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1209422 ofs=712704
-       <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1408387 ofs=716800
-       <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1197336 ofs=720896
-       <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1205652 ofs=724992
-       <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1133421 ofs=729088
-       <unknown>-12695 (-----) [004] .... 1920260.586364: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092173 ofs=733184
-       <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1124430 ofs=737280
-       <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1143926 ofs=741376
-       <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1090109 ofs=745472
-       <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1102012 ofs=749568
-       <unknown>-12695 (-----) [004] .... 1920260.586367: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1154930 ofs=753664
-       <unknown>-12695 (-----) [004] .... 1920260.586368: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1132993 ofs=757760
-       <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1430780 ofs=761856
-       <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1197452 ofs=765952
-       <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1075111 ofs=770048
-       <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1275616 ofs=774144
-       <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1444981 ofs=778240
-       <unknown>-12695 (-----) [004] .... 1920260.586371: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1452592 ofs=782336
-       <unknown>-12695 (-----) [004] .... 1920260.586374: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1102857 ofs=786432
-       <unknown>-12695 (-----) [004] .... 1920260.586376: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1406969 ofs=790528
-       <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1522553 ofs=794624
-       <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1260771 ofs=798720
-       <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1474649 ofs=802816
-       <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1268708 ofs=806912
-       <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1346144 ofs=811008
-       <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1081167 ofs=815104
-       <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1137677 ofs=819200
-       <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1161175 ofs=823296
-       <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1461331 ofs=827392
-       <unknown>-12695 (-----) [004] .... 1920260.586492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1347219 ofs=831488
-       <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1290004 ofs=835584
-       <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1299174 ofs=839680
-       <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1317595 ofs=843776
-       <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1484924 ofs=847872
-       <unknown>-12695 (-----) [004] .... 1920260.586497: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1169920 ofs=851968
-       <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1359189 ofs=856064
-       <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1307842 ofs=860160
-       <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1237858 ofs=864256
-       <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189461 ofs=868352
-       <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1223232 ofs=872448
-       <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1104076 ofs=876544
-       <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1079223 ofs=880640
-       <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092537 ofs=884736
-       <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1353960 ofs=888832
-       <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1346330 ofs=892928
-       <unknown>-12695 (-----) [004] .... 1920260.586506: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1345764 ofs=897024
-       <unknown>-12695 (-----) [004] .... 1920260.586507: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1363913 ofs=901120
-       <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1319570 ofs=905216
-       <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1367024 ofs=909312
-       <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1333808 ofs=913408
-       <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1158627 ofs=917504
-       <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1300368 ofs=921600
-       <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1245363 ofs=925696
-       <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1345609 ofs=929792
-       <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1393826 ofs=933888
-       <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1200552 ofs=937984
-       <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1170885 ofs=942080
-       <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1536209 ofs=946176
-       <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189630 ofs=950272
-       <unknown>-12695 (-----) [004] .... 1920260.586513: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1121010 ofs=954368
-       <unknown>-12695 (-----) [004] .... 1920260.586514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1324474 ofs=958464
-       <unknown>-12697 (-----) [007] .... 1920260.586578: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1129628 ofs=299008
-       <unknown>-12697 (-----) [007] .... 1920260.586579: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1307120 ofs=303104
-       <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1347284 ofs=307200
-       <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1312996 ofs=311296
-       <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1170623 ofs=315392
-       <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1359281 ofs=319488
-       <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1180021 ofs=323584
-       <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1195728 ofs=327680
-       <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1163642 ofs=331776
-       <unknown>-12697 (-----) [007] .... 1920260.586587: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1152538 ofs=335872
-       <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1345922 ofs=339968
-       <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1343604 ofs=344064
-       <unknown>-12697 (-----) [007] .... 1920260.586721: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1399371 ofs=479232
-       <unknown>-12697 (-----) [007] .... 1920260.586723: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1106549 ofs=483328
-       <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331546 ofs=487424
-       <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1299299 ofs=491520
-       <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1288883 ofs=495616
-       <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1399049 ofs=499712
-       <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1146931 ofs=503808
-       <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1296592 ofs=507904
-       <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1468397 ofs=512000
-       <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1215698 ofs=516096
-       <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1177341 ofs=520192
-       <unknown>-12697 (-----) [007] .... 1920260.586731: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189162 ofs=524288
-       <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1435997 ofs=528384
-       <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1209896 ofs=532480
-       <unknown>-12697 (-----) [007] .... 1920260.586733: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1255888 ofs=536576
-       <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1234200 ofs=540672
-       <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1422854 ofs=544768
-       <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1435794 ofs=548864
-       <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1236279 ofs=552960
-       <unknown>-12697 (-----) [007] .... 1920260.586736: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1485732 ofs=557056
-       <unknown>-12683 (-----) [005] .... 1920260.586743: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1417198 ofs=561152
-       <unknown>-12683 (-----) [005] .... 1920260.586746: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1469450 ofs=565248
-       <unknown>-12696 (-----) [004] .... 1920260.587465: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1489023 ofs=1040384
-       <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449498 ofs=1044480
-       <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1447737 ofs=1048576
-       <unknown>-12696 (-----) [004] .... 1920260.587470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1124530 ofs=1052672
-       <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1246743 ofs=1056768
-       <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1441927 ofs=1060864
-       <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1280581 ofs=1064960
-       <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289438 ofs=1069056
-       <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1464236 ofs=1073152
-       <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1125808 ofs=1077248
-       <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1329385 ofs=1081344
-       <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1314093 ofs=1085440
-       <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1201837 ofs=1089536
-       <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1327734 ofs=1093632
-       <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1406568 ofs=1097728
-       <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331873 ofs=1101824
-       <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331898 ofs=1105920
-       <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331917 ofs=1110016
-       <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1332091 ofs=1114112
-       <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1108186 ofs=1118208
-       <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1182631 ofs=1122304
-       <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1085941 ofs=1126400
-       <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1433982 ofs=1130496
-       <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1387028 ofs=1134592
-       <unknown>-12696 (-----) [004] .... 1920260.587488: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1353117 ofs=1138688
-       <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1352364 ofs=1142784
-       <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1144513 ofs=1146880
-       <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1403984 ofs=1150976
-       <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1278970 ofs=1155072
-       <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1326743 ofs=1159168
-       <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1221809 ofs=1163264
-       <unknown>-12696 (-----) [004] .... 1920260.587492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1268668 ofs=1167360
-       <unknown>-12695 (-----) [005] .... 1920260.587502: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1074544 ofs=962560
-       <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1074294 ofs=966656
-       <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1075097 ofs=970752
-       <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1162407 ofs=974848
-       <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1141370 ofs=978944
-       <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306487 ofs=983040
-       <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306434 ofs=987136
-       <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306347 ofs=991232
-       <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306247 ofs=995328
-       <unknown>-12695 (-----) [005] .... 1920260.587515: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306195 ofs=999424
-       <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306039 ofs=1003520
-       <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1305983 ofs=1007616
-       <unknown>-12694 (-----) [006] .... 1920260.587701: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1216391 ofs=1171456
-       <unknown>-12694 (-----) [006] .... 1920260.587705: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1262462 ofs=1175552
-       <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1358114 ofs=1179648
-       <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1357898 ofs=1183744
-       <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1237003 ofs=1187840
-       <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1126319 ofs=1191936
-       <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1415489 ofs=1196032
-       <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1279558 ofs=1200128
-       <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1434022 ofs=1204224
-       <unknown>-12694 (-----) [006] .... 1920260.587709: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1220130 ofs=1208320
-       <unknown>-12694 (-----) [006] .... 1920260.587710: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1163037 ofs=1212416
-       <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1404501 ofs=1216512
-       <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1406287 ofs=1220608
-       <unknown>-12697 (-----) [007] .... 1920260.588132: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1355143 ofs=1376256
-       <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1213923 ofs=1380352
-       <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1243190 ofs=1384448
-       <unknown>-12697 (-----) [007] .... 1920260.588143: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1300698 ofs=1388544
-       <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1482568 ofs=1392640
-       <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1461789 ofs=1396736
-       <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242314 ofs=1400832
-       <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1471996 ofs=1404928
-       <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242742 ofs=1409024
-       <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242579 ofs=1413120
-       <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242553 ofs=1417216
-       <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1457332 ofs=1421312
-       <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1315431 ofs=1425408
-       <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1080653 ofs=1429504
-       <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1324174 ofs=1433600
-       <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1324142 ofs=1437696
-       <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1157760 ofs=1441792
-       <unknown>-12697 (-----) [007] .... 1920260.588151: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1075059 ofs=1445888
-       <unknown>-12683 (-----) [006] .... 1920260.589785: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1279192 ofs=1486848
-       <unknown>-12683 (-----) [006] .... 1920260.589790: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1278527 ofs=1490944
-       <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1091778 ofs=1495040
-       <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1339447 ofs=1499136
-       <unknown>-12683 (-----) [006] .... 1920260.589792: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1254007 ofs=1503232
-       <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1115173 ofs=1507328
-       <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1393985 ofs=1511424
-       <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1369123 ofs=1515520
-       <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1314257 ofs=1519616
-       <unknown>-12683 (-----) [006] .... 1920260.589802: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1404487 ofs=1523712
-       <unknown>-12683 (-----) [006] .... 1920260.589803: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1354554 ofs=1527808
-       <unknown>-12683 (-----) [006] .... 1920260.594312: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1141445 ofs=9801728
+       <unknown>-12683 (-----) [004] .... 1920260.584304: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347409 ofs=0
+       <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1428681 ofs=4096
+       <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1259106 ofs=8192
+       <unknown>-12683 (-----) [004] .... 1920260.584308: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1343229 ofs=12288
+       <unknown>-12694 (-----) [005] .... 1920260.584622: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1098733 ofs=1531904
+       <unknown>-12696 (-----) [006] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331319 ofs=1536000
+       <unknown>-12694 (-----) [005] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278537 ofs=1540096
+       <unknown>-12696 (-----) [006] .... 1920260.584631: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1492534 ofs=1544192
+       <unknown>-12694 (-----) [005] .... 1920260.584636: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1460878 ofs=1548288
+       <unknown>-12694 (-----) [005] .... 1920260.584640: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092973 ofs=1552384
+       <unknown>-12694 (-----) [005] .... 1920260.584641: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1103200 ofs=1556480
+       <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1257426 ofs=1560576
+       <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1219424 ofs=1564672
+       <unknown>-12683 (-----) [004] .... 1920260.584660: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279352 ofs=1568768
+       <unknown>-12696 (-----) [006] .... 1920260.584662: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260572 ofs=1572864
+       <unknown>-12683 (-----) [004] .... 1920260.584663: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1225809 ofs=1576960
+       <unknown>-12696 (-----) [006] .... 1920260.584665: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1350766 ofs=1585152
+       <unknown>-12697 (-----) [007] .... 1920260.584666: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1107173 ofs=1581056
+       <unknown>-12683 (-----) [004] .... 1920260.584668: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1305885 ofs=1589248
+       <unknown>-12694 (-----) [005] .... 1920260.584669: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1293385 ofs=1593344
+       <unknown>-12696 (-----) [006] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1173841 ofs=1597440
+       <unknown>-12697 (-----) [007] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080021 ofs=1601536
+       <unknown>-12683 (-----) [004] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1147419 ofs=1605632
+       <unknown>-12696 (-----) [006] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1252762 ofs=1609728
+       <unknown>-12694 (-----) [005] .... 1920260.584674: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1323916 ofs=1613824
+       <unknown>-12683 (-----) [004] .... 1920260.584675: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1155631 ofs=1617920
+       <unknown>-12696 (-----) [006] .... 1920260.584676: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449815 ofs=1622016
+       <unknown>-12694 (-----) [005] .... 1920260.584678: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1227069 ofs=1626112
+       <unknown>-12696 (-----) [006] .... 1920260.584680: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1317692 ofs=1630208
+       <unknown>-12694 (-----) [005] .... 1920260.584681: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1492244 ofs=1634304
+       <unknown>-12683 (-----) [004] .... 1920260.584682: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241876 ofs=1638400
+       <unknown>-12697 (-----) [007] .... 1920260.585446: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1402958 ofs=167936
+       <unknown>-12697 (-----) [007] .... 1920260.585449: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1133263 ofs=172032
+       <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1295502 ofs=176128
+       <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1249495 ofs=180224
+       <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237999 ofs=184320
+       <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1280965 ofs=188416
+       <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1208361 ofs=192512
+       <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1308840 ofs=196608
+       <unknown>-12695 (-----) [004] .... 1920260.585455: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1138875 ofs=569344
+       <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314886 ofs=573440
+       <unknown>-12697 (-----) [007] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242734 ofs=200704
+       <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447386 ofs=577536
+       <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241302 ofs=204800
+       <unknown>-12695 (-----) [004] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1328663 ofs=581632
+       <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1476101 ofs=208896
+       <unknown>-12695 (-----) [004] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209461 ofs=585728
+       <unknown>-12697 (-----) [007] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080147 ofs=212992
+       <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128509 ofs=217088
+       <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1371915 ofs=221184
+       <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1264015 ofs=225280
+       <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1211695 ofs=229376
+       <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1150386 ofs=233472
+       <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1135747 ofs=237568
+       <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128230 ofs=241664
+       <unknown>-12697 (-----) [007] .... 1920260.585464: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1155451 ofs=245760
+       <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1246841 ofs=249856
+       <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1462971 ofs=253952
+       <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1131333 ofs=258048
+       <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289407 ofs=262144
+       <unknown>-12695 (-----) [004] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1134730 ofs=589824
+       <unknown>-12697 (-----) [007] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289873 ofs=266240
+       <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448734 ofs=270336
+       <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1129776 ofs=593920
+       <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524090 ofs=274432
+       <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399725 ofs=598016
+       <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524081 ofs=278528
+       <unknown>-12695 (-----) [004] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1276535 ofs=602112
+       <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524060 ofs=282624
+       <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449847 ofs=606208
+       <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1158944 ofs=286720
+       <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1384536 ofs=610304
+       <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1116785 ofs=290816
+       <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1308118 ofs=614400
+       <unknown>-12697 (-----) [007] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448669 ofs=294912
+       <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1227050 ofs=618496
+       <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289324 ofs=622592
+       <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1187869 ofs=626688
+       <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1400523 ofs=630784
+       <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1344176 ofs=634880
+       <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092871 ofs=638976
+       <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092021 ofs=643072
+       <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1198169 ofs=647168
+       <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1371540 ofs=651264
+       <unknown>-12683 (-----) [005] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1195003 ofs=348160
+       <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1228787 ofs=655360
+       <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1236123 ofs=659456
+       <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1137213 ofs=663552
+       <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1294618 ofs=667648
+       <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241048 ofs=671744
+       <unknown>-12695 (-----) [004] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1228779 ofs=675840
+       <unknown>-12683 (-----) [005] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1199292 ofs=352256
+       <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200861 ofs=356352
+       <unknown>-12695 (-----) [004] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1309572 ofs=679936
+       <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1215770 ofs=360448
+       <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1409002 ofs=684032
+       <unknown>-12683 (-----) [005] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1151883 ofs=364544
+       <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1103729 ofs=688128
+       <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1468126 ofs=368640
+       <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1162720 ofs=692224
+       <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1251672 ofs=372736
+       <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1199221 ofs=696320
+       <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1283325 ofs=376832
+       <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1190489 ofs=380928
+       <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1489117 ofs=385024
+       <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1273899 ofs=389120
+       <unknown>-12683 (-----) [005] .... 1920260.585485: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1274459 ofs=393216
+       <unknown>-12683 (-----) [005] .... 1920260.585486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1316649 ofs=397312
+       <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1375678 ofs=401408
+       <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1483317 ofs=405504
+       <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1240286 ofs=409600
+       <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1131345 ofs=413696
+       <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200483 ofs=417792
+       <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1384693 ofs=421888
+       <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1161385 ofs=425984
+       <unknown>-12683 (-----) [005] .... 1920260.585494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1452025 ofs=430080
+       <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1253654 ofs=434176
+       <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1116697 ofs=438272
+       <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1432645 ofs=442368
+       <unknown>-12694 (-----) [006] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1337397 ofs=16384
+       <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1304229 ofs=446464
+       <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1419147 ofs=450560
+       <unknown>-12683 (-----) [005] .... 1920260.585498: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1349246 ofs=454656
+       <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128519 ofs=458752
+       <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1125168 ofs=462848
+       <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1081031 ofs=20480
+       <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1293022 ofs=24576
+       <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1113007 ofs=28672
+       <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1339312 ofs=32768
+       <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1412311 ofs=36864
+       <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260960 ofs=40960
+       <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189529 ofs=45056
+       <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1412184 ofs=49152
+       <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1481227 ofs=53248
+       <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1455940 ofs=57344
+       <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299132 ofs=61440
+       <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1337375 ofs=65536
+       <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1328742 ofs=69632
+       <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1315646 ofs=73728
+       <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1225475 ofs=77824
+       <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1146097 ofs=81920
+       <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1318775 ofs=86016
+       <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448391 ofs=90112
+       <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1441412 ofs=94208
+       <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1138111 ofs=98304
+       <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1143223 ofs=102400
+       <unknown>-12683 (-----) [005] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1079876 ofs=466944
+       <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447637 ofs=106496
+       <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1220585 ofs=110592
+       <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449051 ofs=114688
+       <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313180 ofs=118784
+       <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313166 ofs=122880
+       <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313154 ofs=126976
+       <unknown>-12683 (-----) [005] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1218394 ofs=471040
+       <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1144047 ofs=131072
+       <unknown>-12683 (-----) [005] .... 1920260.585537: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1218579 ofs=475136
+       <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241332 ofs=135168
+       <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1097199 ofs=139264
+       <unknown>-12694 (-----) [006] .... 1920260.585545: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1214197 ofs=143360
+       <unknown>-12694 (-----) [006] .... 1920260.585645: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197633 ofs=147456
+       <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1311536 ofs=151552
+       <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1322952 ofs=155648
+       <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346974 ofs=159744
+       <unknown>-12694 (-----) [006] .... 1920260.585648: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1257232 ofs=163840
+       <unknown>-12695 (-----) [004] .... 1920260.586355: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1204484 ofs=700416
+       <unknown>-12695 (-----) [004] .... 1920260.586357: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1326426 ofs=704512
+       <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1151808 ofs=708608
+       <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209422 ofs=712704
+       <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1408387 ofs=716800
+       <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197336 ofs=720896
+       <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1205652 ofs=724992
+       <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1133421 ofs=729088
+       <unknown>-12695 (-----) [004] .... 1920260.586364: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092173 ofs=733184
+       <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1124430 ofs=737280
+       <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1143926 ofs=741376
+       <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1090109 ofs=745472
+       <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1102012 ofs=749568
+       <unknown>-12695 (-----) [004] .... 1920260.586367: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1154930 ofs=753664
+       <unknown>-12695 (-----) [004] .... 1920260.586368: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1132993 ofs=757760
+       <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1430780 ofs=761856
+       <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197452 ofs=765952
+       <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075111 ofs=770048
+       <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1275616 ofs=774144
+       <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1444981 ofs=778240
+       <unknown>-12695 (-----) [004] .... 1920260.586371: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1452592 ofs=782336
+       <unknown>-12695 (-----) [004] .... 1920260.586374: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1102857 ofs=786432
+       <unknown>-12695 (-----) [004] .... 1920260.586376: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406969 ofs=790528
+       <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1522553 ofs=794624
+       <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260771 ofs=798720
+       <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1474649 ofs=802816
+       <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1268708 ofs=806912
+       <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346144 ofs=811008
+       <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1081167 ofs=815104
+       <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1137677 ofs=819200
+       <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1161175 ofs=823296
+       <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1461331 ofs=827392
+       <unknown>-12695 (-----) [004] .... 1920260.586492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347219 ofs=831488
+       <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1290004 ofs=835584
+       <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299174 ofs=839680
+       <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1317595 ofs=843776
+       <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1484924 ofs=847872
+       <unknown>-12695 (-----) [004] .... 1920260.586497: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1169920 ofs=851968
+       <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1359189 ofs=856064
+       <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1307842 ofs=860160
+       <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237858 ofs=864256
+       <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189461 ofs=868352
+       <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1223232 ofs=872448
+       <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1104076 ofs=876544
+       <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1079223 ofs=880640
+       <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092537 ofs=884736
+       <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1353960 ofs=888832
+       <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346330 ofs=892928
+       <unknown>-12695 (-----) [004] .... 1920260.586506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345764 ofs=897024
+       <unknown>-12695 (-----) [004] .... 1920260.586507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1363913 ofs=901120
+       <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1319570 ofs=905216
+       <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1367024 ofs=909312
+       <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1333808 ofs=913408
+       <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1158627 ofs=917504
+       <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1300368 ofs=921600
+       <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1245363 ofs=925696
+       <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345609 ofs=929792
+       <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1393826 ofs=933888
+       <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200552 ofs=937984
+       <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1170885 ofs=942080
+       <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1536209 ofs=946176
+       <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189630 ofs=950272
+       <unknown>-12695 (-----) [004] .... 1920260.586513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1121010 ofs=954368
+       <unknown>-12695 (-----) [004] .... 1920260.586514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324474 ofs=958464
+       <unknown>-12697 (-----) [007] .... 1920260.586578: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1129628 ofs=299008
+       <unknown>-12697 (-----) [007] .... 1920260.586579: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1307120 ofs=303104
+       <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347284 ofs=307200
+       <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1312996 ofs=311296
+       <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1170623 ofs=315392
+       <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1359281 ofs=319488
+       <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1180021 ofs=323584
+       <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1195728 ofs=327680
+       <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1163642 ofs=331776
+       <unknown>-12697 (-----) [007] .... 1920260.586587: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1152538 ofs=335872
+       <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345922 ofs=339968
+       <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1343604 ofs=344064
+       <unknown>-12697 (-----) [007] .... 1920260.586721: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399371 ofs=479232
+       <unknown>-12697 (-----) [007] .... 1920260.586723: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1106549 ofs=483328
+       <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331546 ofs=487424
+       <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299299 ofs=491520
+       <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1288883 ofs=495616
+       <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399049 ofs=499712
+       <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1146931 ofs=503808
+       <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1296592 ofs=507904
+       <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1468397 ofs=512000
+       <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1215698 ofs=516096
+       <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1177341 ofs=520192
+       <unknown>-12697 (-----) [007] .... 1920260.586731: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189162 ofs=524288
+       <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1435997 ofs=528384
+       <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209896 ofs=532480
+       <unknown>-12697 (-----) [007] .... 1920260.586733: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1255888 ofs=536576
+       <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1234200 ofs=540672
+       <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1422854 ofs=544768
+       <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1435794 ofs=548864
+       <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1236279 ofs=552960
+       <unknown>-12697 (-----) [007] .... 1920260.586736: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1485732 ofs=557056
+       <unknown>-12683 (-----) [005] .... 1920260.586743: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1417198 ofs=561152
+       <unknown>-12683 (-----) [005] .... 1920260.586746: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1469450 ofs=565248
+       <unknown>-12696 (-----) [004] .... 1920260.587465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1489023 ofs=1040384
+       <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449498 ofs=1044480
+       <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447737 ofs=1048576
+       <unknown>-12696 (-----) [004] .... 1920260.587470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1124530 ofs=1052672
+       <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1246743 ofs=1056768
+       <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1441927 ofs=1060864
+       <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1280581 ofs=1064960
+       <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289438 ofs=1069056
+       <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1464236 ofs=1073152
+       <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1125808 ofs=1077248
+       <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1329385 ofs=1081344
+       <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314093 ofs=1085440
+       <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1201837 ofs=1089536
+       <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1327734 ofs=1093632
+       <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406568 ofs=1097728
+       <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331873 ofs=1101824
+       <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331898 ofs=1105920
+       <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331917 ofs=1110016
+       <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1332091 ofs=1114112
+       <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1108186 ofs=1118208
+       <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1182631 ofs=1122304
+       <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1085941 ofs=1126400
+       <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1433982 ofs=1130496
+       <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1387028 ofs=1134592
+       <unknown>-12696 (-----) [004] .... 1920260.587488: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1353117 ofs=1138688
+       <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1352364 ofs=1142784
+       <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1144513 ofs=1146880
+       <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1403984 ofs=1150976
+       <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278970 ofs=1155072
+       <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1326743 ofs=1159168
+       <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1221809 ofs=1163264
+       <unknown>-12696 (-----) [004] .... 1920260.587492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1268668 ofs=1167360
+       <unknown>-12695 (-----) [005] .... 1920260.587502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1074544 ofs=962560
+       <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1074294 ofs=966656
+       <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075097 ofs=970752
+       <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1162407 ofs=974848
+       <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1141370 ofs=978944
+       <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306487 ofs=983040
+       <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306434 ofs=987136
+       <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306347 ofs=991232
+       <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306247 ofs=995328
+       <unknown>-12695 (-----) [005] .... 1920260.587515: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306195 ofs=999424
+       <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306039 ofs=1003520
+       <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1305983 ofs=1007616
+       <unknown>-12694 (-----) [006] .... 1920260.587701: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1216391 ofs=1171456
+       <unknown>-12694 (-----) [006] .... 1920260.587705: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1262462 ofs=1175552
+       <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1358114 ofs=1179648
+       <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1357898 ofs=1183744
+       <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237003 ofs=1187840
+       <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1126319 ofs=1191936
+       <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1415489 ofs=1196032
+       <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279558 ofs=1200128
+       <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1434022 ofs=1204224
+       <unknown>-12694 (-----) [006] .... 1920260.587709: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1220130 ofs=1208320
+       <unknown>-12694 (-----) [006] .... 1920260.587710: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1163037 ofs=1212416
+       <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1404501 ofs=1216512
+       <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406287 ofs=1220608
+       <unknown>-12697 (-----) [007] .... 1920260.588132: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1355143 ofs=1376256
+       <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1213923 ofs=1380352
+       <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1243190 ofs=1384448
+       <unknown>-12697 (-----) [007] .... 1920260.588143: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1300698 ofs=1388544
+       <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1482568 ofs=1392640
+       <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1461789 ofs=1396736
+       <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242314 ofs=1400832
+       <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1471996 ofs=1404928
+       <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242742 ofs=1409024
+       <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242579 ofs=1413120
+       <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242553 ofs=1417216
+       <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1457332 ofs=1421312
+       <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1315431 ofs=1425408
+       <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080653 ofs=1429504
+       <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324174 ofs=1433600
+       <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324142 ofs=1437696
+       <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1157760 ofs=1441792
+       <unknown>-12697 (-----) [007] .... 1920260.588151: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075059 ofs=1445888
+       <unknown>-12683 (-----) [006] .... 1920260.589785: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279192 ofs=1486848
+       <unknown>-12683 (-----) [006] .... 1920260.589790: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278527 ofs=1490944
+       <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1091778 ofs=1495040
+       <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1339447 ofs=1499136
+       <unknown>-12683 (-----) [006] .... 1920260.589792: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1254007 ofs=1503232
+       <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1115173 ofs=1507328
+       <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1393985 ofs=1511424
+       <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1369123 ofs=1515520
+       <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314257 ofs=1519616
+       <unknown>-12683 (-----) [006] .... 1920260.589802: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1404487 ofs=1523712
+       <unknown>-12683 (-----) [006] .... 1920260.589803: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1354554 ofs=1527808
+       <unknown>-12683 (-----) [006] .... 1920260.594312: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1141445 ofs=9801728
        <unknown>-12683 (-----) [006] .... 1920260.594322: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323774 ofs=231460864
        <unknown>-12683 (-----) [006] .... 1920260.594326: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323772 ofs=10993664
-       <unknown>-12683 (-----) [006] .... 1920260.595212: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481305 ofs=9805824
-       <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481306 ofs=9809920
-       <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481316 ofs=9814016
-       <unknown>-12683 (-----) [006] .... 1920260.595215: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481340 ofs=9818112
-       <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1394587 ofs=9822208
-       <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103455 ofs=9826304
-       <unknown>-12683 (-----) [006] .... 1920260.595217: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103271 ofs=9830400
-       <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103168 ofs=9834496
-       <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103145 ofs=9838592
-       <unknown>-12683 (-----) [006] .... 1920260.595219: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103115 ofs=9842688
-       <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103057 ofs=9846784
-       <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1331958 ofs=9850880
-       <unknown>-12683 (-----) [006] .... 1920260.595227: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1356305 ofs=9854976
-       <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103708 ofs=9859072
-       <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1099286 ofs=9863168
-       <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1435190 ofs=9867264
-       <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1395504 ofs=9871360
-       <unknown>-12683 (-----) [006] .... 1920260.595230: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1352916 ofs=9875456
-       <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1255529 ofs=9879552
-       <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1336145 ofs=9883648
-       <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1334143 ofs=9887744
-       <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1328548 ofs=9891840
-       <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1222215 ofs=9895936
-       <unknown>-12683 (-----) [006] .... 1920260.595233: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1461056 ofs=9900032
-       <unknown>-12683 (-----) [006] .... 1920260.595234: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1228276 ofs=9904128
-       <unknown>-12683 (-----) [006] .... 1920260.595235: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1151188 ofs=9908224
-       <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1443605 ofs=9912320
-       <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1146821 ofs=9916416
-       <unknown>-12683 (-----) [006] .... 1920260.595237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103669 ofs=9920512
-       <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103744 ofs=9924608
-       <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103868 ofs=9928704
-       <unknown>-12683 (-----) [006] .... 1920260.595789: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1465942 ofs=15855616
+       <unknown>-12683 (-----) [006] .... 1920260.595212: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481305 ofs=9805824
+       <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481306 ofs=9809920
+       <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481316 ofs=9814016
+       <unknown>-12683 (-----) [006] .... 1920260.595215: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481340 ofs=9818112
+       <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1394587 ofs=9822208
+       <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103455 ofs=9826304
+       <unknown>-12683 (-----) [006] .... 1920260.595217: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103271 ofs=9830400
+       <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103168 ofs=9834496
+       <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103145 ofs=9838592
+       <unknown>-12683 (-----) [006] .... 1920260.595219: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103115 ofs=9842688
+       <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103057 ofs=9846784
+       <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1331958 ofs=9850880
+       <unknown>-12683 (-----) [006] .... 1920260.595227: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1356305 ofs=9854976
+       <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103708 ofs=9859072
+       <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1099286 ofs=9863168
+       <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435190 ofs=9867264
+       <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1395504 ofs=9871360
+       <unknown>-12683 (-----) [006] .... 1920260.595230: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1352916 ofs=9875456
+       <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1255529 ofs=9879552
+       <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1336145 ofs=9883648
+       <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1334143 ofs=9887744
+       <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1328548 ofs=9891840
+       <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1222215 ofs=9895936
+       <unknown>-12683 (-----) [006] .... 1920260.595233: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1461056 ofs=9900032
+       <unknown>-12683 (-----) [006] .... 1920260.595234: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1228276 ofs=9904128
+       <unknown>-12683 (-----) [006] .... 1920260.595235: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1151188 ofs=9908224
+       <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1443605 ofs=9912320
+       <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1146821 ofs=9916416
+       <unknown>-12683 (-----) [006] .... 1920260.595237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103669 ofs=9920512
+       <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103744 ofs=9924608
+       <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103868 ofs=9928704
+       <unknown>-12683 (-----) [006] .... 1920260.595789: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1465942 ofs=15855616
        <unknown>-12683 (-----) [006] .... 1920260.595792: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323712 ofs=261189632
        <unknown>-12683 (-----) [006] .... 1920260.595998: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323701 ofs=262094848
-       <unknown>-12683 (-----) [006] .... 1920260.596191: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1222287 ofs=15859712
-       <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1213146 ofs=15863808
-       <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1310396 ofs=15867904
-       <unknown>-12683 (-----) [006] .... 1920260.596193: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1310177 ofs=15872000
-       <unknown>-12683 (-----) [006] .... 1920260.596194: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1187914 ofs=15876096
-       <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1322409 ofs=15880192
-       <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1282484 ofs=15884288
-       <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1097245 ofs=15888384
-       <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1416816 ofs=15892480
-       <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1257125 ofs=15896576
-       <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1403527 ofs=15900672
-       <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1218006 ofs=15904768
-       <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1153893 ofs=15908864
-       <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1328023 ofs=15912960
-       <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1465412 ofs=15917056
-       <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1092448 ofs=15921152
-       <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1239220 ofs=15925248
-       <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1276491 ofs=15929344
-       <unknown>-12683 (-----) [006] .... 1920260.596205: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1262240 ofs=15933440
-       <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1323793 ofs=15937536
-       <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1074937 ofs=15941632
-       <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1311157 ofs=15945728
-       <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1308442 ofs=15949824
-       <unknown>-12683 (-----) [006] .... 1920260.596210: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1467709 ofs=15953920
-       <unknown>-12683 (-----) [006] .... 1920260.596211: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1394299 ofs=15958016
-       <unknown>-12683 (-----) [004] .... 1920260.612586: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1316156 ofs=344064
-       <unknown>-12683 (-----) [004] .... 1920260.612591: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1406323 ofs=348160
-       <unknown>-12683 (-----) [004] .... 1920260.612601: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1216972 ofs=352256
-       <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1271924 ofs=356352
-       <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1369225 ofs=360448
-       <unknown>-12683 (-----) [004] .... 1920260.612608: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1318474 ofs=364544
-       <unknown>-12683 (-----) [004] .... 1920260.612609: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1227283 ofs=368640
-       <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1364376 ofs=372736
-       <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1073400 ofs=376832
+       <unknown>-12683 (-----) [006] .... 1920260.596191: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1222287 ofs=15859712
+       <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1213146 ofs=15863808
+       <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1310396 ofs=15867904
+       <unknown>-12683 (-----) [006] .... 1920260.596193: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1310177 ofs=15872000
+       <unknown>-12683 (-----) [006] .... 1920260.596194: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1187914 ofs=15876096
+       <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1322409 ofs=15880192
+       <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1282484 ofs=15884288
+       <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1097245 ofs=15888384
+       <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1416816 ofs=15892480
+       <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1257125 ofs=15896576
+       <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1403527 ofs=15900672
+       <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1218006 ofs=15904768
+       <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1153893 ofs=15908864
+       <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1328023 ofs=15912960
+       <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1465412 ofs=15917056
+       <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1092448 ofs=15921152
+       <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1239220 ofs=15925248
+       <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1276491 ofs=15929344
+       <unknown>-12683 (-----) [006] .... 1920260.596205: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1262240 ofs=15933440
+       <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1323793 ofs=15937536
+       <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1074937 ofs=15941632
+       <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1311157 ofs=15945728
+       <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1308442 ofs=15949824
+       <unknown>-12683 (-----) [006] .... 1920260.596210: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1467709 ofs=15953920
+       <unknown>-12683 (-----) [006] .... 1920260.596211: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1394299 ofs=15958016
+       <unknown>-12683 (-----) [004] .... 1920260.612586: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1316156 ofs=344064
+       <unknown>-12683 (-----) [004] .... 1920260.612591: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1406323 ofs=348160
+       <unknown>-12683 (-----) [004] .... 1920260.612601: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1216972 ofs=352256
+       <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1271924 ofs=356352
+       <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1369225 ofs=360448
+       <unknown>-12683 (-----) [004] .... 1920260.612608: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1318474 ofs=364544
+       <unknown>-12683 (-----) [004] .... 1920260.612609: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1227283 ofs=368640
+       <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1364376 ofs=372736
+       <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1073400 ofs=376832
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 5e71416..60290e3 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -728,6 +728,7 @@
         }
 
         /** {@hide} */
+        @TestApi
         public String getTelecomCallId() {
             return mTelecomCallId;
         }
@@ -2048,6 +2049,10 @@
                 return "DISCONNECTING";
             case STATE_SELECT_PHONE_ACCOUNT:
                 return "SELECT_PHONE_ACCOUNT";
+            case STATE_SIMULATED_RINGING:
+                return "SIMULATED_RINGING";
+            case STATE_AUDIO_PROCESSING:
+                return "AUDIO_PROCESSING";
             default:
                 Log.w(Call.class, "Unknown state %d", state);
                 return "UNKNOWN";
@@ -2137,6 +2142,9 @@
         }
 
         int state = parcelableCall.getState();
+        if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
+            state = Call.STATE_RINGING;
+        }
         boolean stateChanged = mState != state;
         if (stateChanged) {
             mState = state;
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 0d97567..ef1c790 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -374,6 +374,8 @@
                         new ComponentName(getPackageName(), getClass().getName()));
             } else if (response.getSilenceCall()) {
                 mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId());
+            } else if (response.getShouldScreenCallFurther()) {
+                mCallScreeningAdapter.screenCallFurther(callDetails.getTelecomCallId());
             } else {
                 mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
             }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 525b938..fa16b84 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -267,8 +267,13 @@
 
     /**
      * Speed up audio setup for MT call.
+     * <p>
+     * Used for IMS calls to indicate that mobile-terminated (incoming) call audio setup should take
+     * place as soon as the device answers the call, but prior to it being connected.  This is an
+     * optimization some IMS stacks depend on to ensure prompt setup of call audio.
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
 
     /**
@@ -305,6 +310,7 @@
      * device.
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 0x00200000;
 
     /**
@@ -346,28 +352,40 @@
 
     /**
      * Indicates that the current device callback number should be shown.
-     *
+     * <p>
+     * Supports Telephony calls where CDMA emergency callback mode is active.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1<<0;
 
     /**
      * Whether the call is a generic conference, where we do not know the precise state of
      * participants in the conference (eg. on CDMA).
-     *
+     * <p>
+     * Supports legacy telephony CDMA calls.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_GENERIC_CONFERENCE = 1<<1;
 
     /**
      * Connection is using high definition audio.
-     * @hide
+     * <p>
+     * Indicates that the {@link Connection} is using a "high definition" audio codec.  This usually
+     * implies something like AMR wideband, but the interpretation of when a call is considered high
+     * definition is left to the {@link ConnectionService} to decide.
+     * <p>
+     * Translates to {@link android.telecom.Call.Details#PROPERTY_HIGH_DEF_AUDIO}.
      */
     public static final int PROPERTY_HIGH_DEF_AUDIO = 1<<2;
 
     /**
      * Connection is using WIFI.
-     * @hide
+     * <p>
+     * Used to indicate that a call is taking place over WIFI versus a carrier network.
+     * <p>
+     * Translates to {@link android.telecom.Call.Details#PROPERTY_WIFI}.
      */
     public static final int PROPERTY_WIFI = 1<<3;
 
@@ -394,8 +412,12 @@
 
     /**
      * Indicates that the connection represents a downgraded IMS conference.
+     * <p>
+     * This property is set when an IMS conference undergoes SRVCC and is re-added to Telecom as a
+     * new entity to indicate that the new connection was a conference.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6;
 
     /**
@@ -421,7 +443,9 @@
     /**
      * Set by the framework to indicate that the network has identified a Connection as an emergency
      * call.
-     * @hide
+     * <p>
+     * This is used for incoming (mobile-terminated) calls to indicate the call is from emergency
+     * services.
      */
     public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1 << 10;
 
@@ -429,8 +453,11 @@
      * Set by the framework to indicate that a Conference or Connection is hosted by a device other
      * than the current one.  Used in scenarios where the conference originator is the remote device
      * and the current device is a participant of that conference.
+     * <p>
+     * This property is specific to IMS conference calls originating in Telephony.
      * @hide
      */
+    @SystemApi
     public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11;
 
     //**********************************************************************************************
@@ -483,8 +510,12 @@
     /**
      * Boolean connection extra key on a {@link Connection} which indicates that adding an
      * additional call is disallowed.
+     * <p>
+     * Used for mobile-network calls to identify scenarios where carrier requirements preclude
+     * adding another call at the current time.
      * @hide
      */
+    @SystemApi
     public static final String EXTRA_DISABLE_ADD_CALL =
             "android.telecom.extra.DISABLE_ADD_CALL";
 
@@ -508,6 +539,9 @@
      * The TelephonyCS will ALSO try to add the existing connection to Telecom, except with the
      * ID it originally referred to the connection as.  Thus Telecom needs to know that the
      * Connection with ID {@code ConnMan@1} is really the same as {@code TelephonyCS@1}.
+     * <p>
+     * This is an internal Telecom framework concept and is not exposed outside of the Telecom
+     * framework.
      * @hide
      */
     public static final String EXTRA_ORIGINAL_CONNECTION_ID =
@@ -525,7 +559,6 @@
      * Connection event used to inform Telecom that it should play the on hold tone.  This is used
      * to play a tone when the peer puts the current call on hold.  Sent to Telecom via
      * {@link #sendConnectionEvent(String, Bundle)}.
-     * @hide
      */
     public static final String EVENT_ON_HOLD_TONE_START =
             "android.telecom.event.ON_HOLD_TONE_START";
@@ -534,7 +567,6 @@
      * Connection event used to inform Telecom that it should stop the on hold tone.  This is used
      * to stop a tone when the peer puts the current call on hold.  Sent to Telecom via
      * {@link #sendConnectionEvent(String, Bundle)}.
-     * @hide
      */
     public static final String EVENT_ON_HOLD_TONE_END =
             "android.telecom.event.ON_HOLD_TONE_END";
@@ -565,10 +597,9 @@
 
     /**
      * Connection event used to inform Telecom when a hold operation on a call has failed.
-     * Not intended for use by the UI at this time.
+     * <p>
      * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
      * expected to be null when this connection event is used.
-     * @hide
      */
     public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED";
 
@@ -578,7 +609,6 @@
      * <p>
      * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
      * expected to be null when this connection event is used.
-     * @hide
      */
     public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START";
 
@@ -588,7 +618,6 @@
      * <p>
      * Sent via {@link #sendConnectionEvent(String, Bundle)}.  The {@link Bundle} parameter is
      * expected to be null when this connection event is used.
-     * @hide
      */
     public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE";
 
@@ -600,7 +629,6 @@
      * call is being held locally on the device.  When a capable {@link ConnectionService} receives
      * signalling to indicate that the remote party has put the call on hold, it can send this
      * connection event.
-     * @hide
      */
     public static final String EVENT_CALL_REMOTELY_HELD =
             "android.telecom.event.CALL_REMOTELY_HELD";
@@ -613,7 +641,6 @@
      * call is being held locally on the device.  When a capable {@link ConnectionService} receives
      * signalling to indicate that the remote party has taken the call off hold, it can send this
      * connection event.
-     * @hide
      */
     public static final String EVENT_CALL_REMOTELY_UNHELD =
             "android.telecom.event.CALL_REMOTELY_UNHELD";
@@ -656,49 +683,6 @@
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
     /**
-     * Whether the given capabilities support the specified capability.
-     *
-     * @param capabilities A capability bit field.
-     * @param capability The capability to check capabilities for.
-     * @return Whether the specified capability is supported.
-     * @hide
-     */
-    public static boolean can(int capabilities, int capability) {
-        return (capabilities & capability) == capability;
-    }
-
-    /**
-     * Whether the capabilities of this {@code Connection} supports the specified capability.
-     *
-     * @param capability The capability to check capabilities for.
-     * @return Whether the specified capability is supported.
-     * @hide
-     */
-    public boolean can(int capability) {
-        return can(mConnectionCapabilities, capability);
-    }
-
-    /**
-     * Removes the specified capability from the set of capabilities of this {@code Connection}.
-     *
-     * @param capability The capability to remove from the set.
-     * @hide
-     */
-    public void removeCapability(int capability) {
-        mConnectionCapabilities &= ~capability;
-    }
-
-    /**
-     * Adds the specified capability to the set of capabilities of this {@code Connection}.
-     *
-     * @param capability The capability to add to the set.
-     * @hide
-     */
-    public void addCapability(int capability) {
-        mConnectionCapabilities |= capability;
-    }
-
-    /**
      * Renders a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
      *
      * @param capabilities A capability bit field.
@@ -727,67 +711,72 @@
             builder.append("Capabilities:");
         }
 
-        if (can(capabilities, CAPABILITY_HOLD)) {
+        if ((capabilities & CAPABILITY_HOLD) == CAPABILITY_HOLD) {
             builder.append(isLong ? " CAPABILITY_HOLD" : " hld");
         }
-        if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
+        if ((capabilities & CAPABILITY_SUPPORT_HOLD) == CAPABILITY_SUPPORT_HOLD) {
             builder.append(isLong ? " CAPABILITY_SUPPORT_HOLD" : " sup_hld");
         }
-        if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
+        if ((capabilities & CAPABILITY_MERGE_CONFERENCE) == CAPABILITY_MERGE_CONFERENCE) {
             builder.append(isLong ? " CAPABILITY_MERGE_CONFERENCE" : " mrg_cnf");
         }
-        if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
+        if ((capabilities & CAPABILITY_SWAP_CONFERENCE) == CAPABILITY_SWAP_CONFERENCE) {
             builder.append(isLong ? " CAPABILITY_SWAP_CONFERENCE" : " swp_cnf");
         }
-        if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
+        if ((capabilities & CAPABILITY_RESPOND_VIA_TEXT) == CAPABILITY_RESPOND_VIA_TEXT) {
             builder.append(isLong ? " CAPABILITY_RESPOND_VIA_TEXT" : " txt");
         }
-        if (can(capabilities, CAPABILITY_MUTE)) {
+        if ((capabilities & CAPABILITY_MUTE) == CAPABILITY_MUTE) {
             builder.append(isLong ? " CAPABILITY_MUTE" : " mut");
         }
-        if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
+        if ((capabilities & CAPABILITY_MANAGE_CONFERENCE) == CAPABILITY_MANAGE_CONFERENCE) {
             builder.append(isLong ? " CAPABILITY_MANAGE_CONFERENCE" : " mng_cnf");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_RX) == CAPABILITY_SUPPORTS_VT_LOCAL_RX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_RX" : " VTlrx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_TX) == CAPABILITY_SUPPORTS_VT_LOCAL_TX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_TX" : " VTltx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
+                == CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL" : " VTlbi");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_RX) == CAPABILITY_SUPPORTS_VT_REMOTE_RX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_RX" : " VTrrx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_TX) == CAPABILITY_SUPPORTS_VT_REMOTE_TX) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_TX" : " VTrtx");
         }
-        if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
+        if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)
+                == CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) {
             builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL" : " VTrbi");
         }
-        if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
+        if ((capabilities & CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)
+                == CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO) {
             builder.append(isLong ? " CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO" : " !v2a");
         }
-        if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
+        if ((capabilities & CAPABILITY_SPEED_UP_MT_AUDIO) == CAPABILITY_SPEED_UP_MT_AUDIO) {
             builder.append(isLong ? " CAPABILITY_SPEED_UP_MT_AUDIO" : " spd_aud");
         }
-        if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
+        if ((capabilities & CAPABILITY_CAN_UPGRADE_TO_VIDEO) == CAPABILITY_CAN_UPGRADE_TO_VIDEO) {
             builder.append(isLong ? " CAPABILITY_CAN_UPGRADE_TO_VIDEO" : " a2v");
         }
-        if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
+        if ((capabilities & CAPABILITY_CAN_PAUSE_VIDEO) == CAPABILITY_CAN_PAUSE_VIDEO) {
             builder.append(isLong ? " CAPABILITY_CAN_PAUSE_VIDEO" : " paus_VT");
         }
-        if (can(capabilities, CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)) {
+        if ((capabilities & CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)
+                == CAPABILITY_CONFERENCE_HAS_NO_CHILDREN) {
             builder.append(isLong ? " CAPABILITY_SINGLE_PARTY_CONFERENCE" : " 1p_cnf");
         }
-        if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
+        if ((capabilities & CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)
+                == CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION) {
             builder.append(isLong ? " CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION" : " rsp_by_con");
         }
-        if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+        if ((capabilities & CAPABILITY_CAN_PULL_CALL) == CAPABILITY_CAN_PULL_CALL) {
             builder.append(isLong ? " CAPABILITY_CAN_PULL_CALL" : " pull");
         }
-        if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
+        if ((capabilities & CAPABILITY_SUPPORT_DEFLECT) == CAPABILITY_SUPPORT_DEFLECT) {
             builder.append(isLong ? " CAPABILITY_SUPPORT_DEFLECT" : " sup_def");
         }
 
@@ -823,43 +812,44 @@
             builder.append("Properties:");
         }
 
-        if (can(properties, PROPERTY_SELF_MANAGED)) {
+        if ((properties & PROPERTY_SELF_MANAGED) == PROPERTY_SELF_MANAGED) {
             builder.append(isLong ? " PROPERTY_SELF_MANAGED" : " self_mng");
         }
 
-        if (can(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
+        if ((properties & PROPERTY_EMERGENCY_CALLBACK_MODE) == PROPERTY_EMERGENCY_CALLBACK_MODE) {
             builder.append(isLong ? " PROPERTY_EMERGENCY_CALLBACK_MODE" : " ecbm");
         }
 
-        if (can(properties, PROPERTY_HIGH_DEF_AUDIO)) {
+        if ((properties & PROPERTY_HIGH_DEF_AUDIO) == PROPERTY_HIGH_DEF_AUDIO) {
             builder.append(isLong ? " PROPERTY_HIGH_DEF_AUDIO" : " HD");
         }
 
-        if (can(properties, PROPERTY_WIFI)) {
+        if ((properties & PROPERTY_WIFI) == PROPERTY_WIFI) {
             builder.append(isLong ? " PROPERTY_WIFI" : " wifi");
         }
 
-        if (can(properties, PROPERTY_GENERIC_CONFERENCE)) {
+        if ((properties & PROPERTY_GENERIC_CONFERENCE) == PROPERTY_GENERIC_CONFERENCE) {
             builder.append(isLong ? " PROPERTY_GENERIC_CONFERENCE" : " gen_conf");
         }
 
-        if (can(properties, PROPERTY_IS_EXTERNAL_CALL)) {
+        if ((properties & PROPERTY_IS_EXTERNAL_CALL) == PROPERTY_IS_EXTERNAL_CALL) {
             builder.append(isLong ? " PROPERTY_IS_EXTERNAL_CALL" : " xtrnl");
         }
 
-        if (can(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
+        if ((properties & PROPERTY_HAS_CDMA_VOICE_PRIVACY) == PROPERTY_HAS_CDMA_VOICE_PRIVACY) {
             builder.append(isLong ? " PROPERTY_HAS_CDMA_VOICE_PRIVACY" : " priv");
         }
 
-        if (can(properties, PROPERTY_IS_RTT)) {
+        if ((properties & PROPERTY_IS_RTT) == PROPERTY_IS_RTT) {
             builder.append(isLong ? " PROPERTY_IS_RTT" : " rtt");
         }
 
-        if (can(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
+        if ((properties & PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)
+                == PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) {
             builder.append(isLong ? " PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL" : " ecall");
         }
 
-        if (can(properties, PROPERTY_REMOTELY_HOSTED)) {
+        if ((properties & PROPERTY_REMOTELY_HOSTED) == PROPERTY_REMOTELY_HOSTED) {
             builder.append(isLong ? " PROPERTY_REMOTELY_HOSTED" : " remote_hst");
         }
 
@@ -889,16 +879,10 @@
         public void onConferenceablesChanged(
                 Connection c, List<Conferenceable> conferenceables) {}
         public void onConferenceChanged(Connection c, Conference conference) {}
-        /** @hide */
-        public void onConferenceParticipantsChanged(Connection c,
-                List<ConferenceParticipant> participants) {}
-        public void onConferenceStarted() {}
         public void onConferenceMergeFailed(Connection c) {}
         public void onExtrasChanged(Connection c, Bundle extras) {}
         public void onExtrasRemoved(Connection c, List<String> keys) {}
         public void onConnectionEvent(Connection c, String event, Bundle extras) {}
-        /** @hide */
-        public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
         public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {}
         public void onRttInitiationSuccess(Connection c) {}
         public void onRttInitiationFailure(Connection c, int reason) {}
@@ -1815,11 +1799,15 @@
     /**
      * Returns the Telecom internal call ID associated with this connection.  Should only be used
      * for debugging and tracing purposes.
+     * <p>
+     * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is
+     * provided to facilitate debugging of the Telephony stack only.
      *
-     * @return The Telecom call ID.
+     * @return The Telecom call ID, or {@code null} if it was not set.
      * @hide
      */
-    public final String getTelecomCallId() {
+    @SystemApi
+    public final @Nullable String getTelecomCallId() {
         return mTelecomCallId;
     }
 
@@ -1868,9 +1856,8 @@
      * {@link VideoProfile#STATE_RX_ENABLED}.
      *
      * @return The video state of the connection.
-     * @hide
      */
-    public final int getVideoState() {
+    public final @VideoProfile.VideoState int getVideoState() {
         return mVideoState;
     }
 
@@ -1926,11 +1913,16 @@
      * Retrieves the connection start time of the {@code Connnection}, if specified.  A value of
      * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the
      * start time of the conference.
+     * <p>
+     * Note: This is an implementation detail specific to IMS conference calls over a mobile
+     * network.
      *
-     * @return The time at which the {@code Connnection} was connected.
+     * @return The time at which the {@code Connnection} was connected. Will be a value as retrieved
+     * from {@link System#currentTimeMillis()}.
      *
      * @hide
      */
+    @SystemApi
     public final long getConnectTimeMillis() {
         return mConnectTimeMillis;
     }
@@ -1939,26 +1931,32 @@
      * Retrieves the connection start time of the {@link Connection}, if specified.  A value of
      * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the
      * start time of the conference.
-     *
+     * <p>
      * Based on the value of {@link SystemClock#elapsedRealtime()}, which ensures that wall-clock
      * changes do not impact the call duration.
+     * <p>
+     * Used internally in Telephony when migrating conference participant data for IMS conferences.
      *
      * @return The time at which the {@link Connection} was connected.
      *
      * @hide
      */
+    @SystemApi
     public final long getConnectElapsedTimeMillis() {
         return mConnectElapsedTimeMillis;
     }
 
     /**
      * Returns RIL voice radio technology used for current connection.
+     * <p>
+     * Used by the Telephony {@link ConnectionService}.
      *
      * @return the RIL voice radio technology used for current connection,
      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      *
      * @hide
      */
+    @SystemApi
     public final @RilRadioTechnology int getCallRadioTech() {
         int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         Bundle extras = getExtras();
@@ -2038,11 +2036,16 @@
     /**
      * Sets the telecom call ID associated with this Connection.  The Telecom Call ID should be used
      * ONLY for debugging purposes.
+     * <p>
+     * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is
+     * provided to facilitate debugging of the Telephony stack only.  Changing the ID via this
+     * method does NOT change any functionality in Telephony or Telecom and impacts only logging.
      *
      * @param callId The telecom call ID.
      * @hide
      */
-    public void setTelecomCallId(String callId) {
+    @SystemApi
+    public void setTelecomCallId(@NonNull String callId) {
         mTelecomCallId = callId;
     }
 
@@ -2379,12 +2382,15 @@
     /**
      * Sets the time at which a call became active on this Connection. This is set only
      * when a conference call becomes active on this connection.
+     * <p>
+     * Used by telephony to maintain calls associated with an IMS Conference.
      *
      * @param connectTimeMillis The connection time, in milliseconds.  Should be set using a value
      *                          obtained from {@link System#currentTimeMillis()}.
      *
      * @hide
      */
+    @SystemApi
     public final void setConnectTimeMillis(long connectTimeMillis) {
         mConnectTimeMillis = connectTimeMillis;
     }
@@ -2392,27 +2398,37 @@
     /**
      * Sets the time at which a call became active on this Connection. This is set only
      * when a conference call becomes active on this connection.
-     *
+     * <p>
+     * Used by telephony to maintain calls associated with an IMS Conference.
      * @param connectElapsedTimeMillis The connection time, in milliseconds.  Stored in the format
      *                              {@link SystemClock#elapsedRealtime()}.
      *
      * @hide
      */
+    @SystemApi
     public final void setConnectionStartElapsedRealTime(long connectElapsedTimeMillis) {
         mConnectElapsedTimeMillis = connectElapsedTimeMillis;
     }
 
     /**
      * Sets RIL voice radio technology used for current connection.
+     * <p>
+     * This property is set by the Telephony {@link ConnectionService}.
      *
      * @param vrat the RIL Voice Radio Technology used for current connection,
      *             see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
      *
      * @hide
      */
+    @SystemApi
     public final void setCallRadioTech(@RilRadioTechnology int vrat) {
-        putExtra(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
+        Bundle extras = getExtras();
+        if (extras == null) {
+            extras = new Bundle();
+        }
+        extras.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
                 ServiceState.rilRadioTechnologyToNetworkType(vrat));
+        putExtras(extras);
         // Propagates the call radio technology to its parent {@link android.telecom.Conference}
         // This action only covers non-IMS CS conference calls.
         // For IMS PS call conference call, it can be updated via its host connection
@@ -2480,9 +2496,12 @@
     }
 
     /**
+     * Resets the CDMA connection time.
+     * <p>
+     * This is an implementation detail specific to legacy CDMA calls on mobile networks.
      * @hide
-     * Resets the cdma connection time.
      */
+    @SystemApi
     public final void resetConnectionTime() {
         for (Listener l : mListeners) {
             l.onConnectionTimeReset(this);
@@ -2522,13 +2541,6 @@
     }
 
     /**
-     * @hide
-     */
-    public final ConnectionService getConnectionService() {
-        return mConnectionService;
-    }
-
-    /**
      * Sets the conference that this connection is a part of. This will fail if the connection is
      * already part of a conference. {@link #resetConference} to un-set the conference first.
      *
@@ -2638,45 +2650,6 @@
     }
 
     /**
-     * Adds a boolean extra to this {@code Connection}.
-     *
-     * @param key The extra key.
-     * @param value The value.
-     * @hide
-     */
-    public final void putExtra(String key, boolean value) {
-        Bundle newExtras = new Bundle();
-        newExtras.putBoolean(key, value);
-        putExtras(newExtras);
-    }
-
-    /**
-     * Adds an integer extra to this {@code Connection}.
-     *
-     * @param key The extra key.
-     * @param value The value.
-     * @hide
-     */
-    public final void putExtra(String key, int value) {
-        Bundle newExtras = new Bundle();
-        newExtras.putInt(key, value);
-        putExtras(newExtras);
-    }
-
-    /**
-     * Adds a string extra to this {@code Connection}.
-     *
-     * @param key The extra key.
-     * @param value The value.
-     * @hide
-     */
-    public final void putExtra(String key, String value) {
-        Bundle newExtras = new Bundle();
-        newExtras.putString(key, value);
-        putExtras(newExtras);
-    }
-
-    /**
      * Removes extras from this {@code Connection}.
      *
      * @param keys The keys of the extras to remove.
@@ -3242,53 +3215,16 @@
     }
 
     /**
-     * Notifies listeners that the merge request failed.
-     *
-     * @hide
+     * Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()}
+     * request failed.
      */
-    protected final void notifyConferenceMergeFailed() {
+    public final void notifyConferenceMergeFailed() {
         for (Listener l : mListeners) {
             l.onConferenceMergeFailed(this);
         }
     }
 
     /**
-     * Notifies listeners of a change to conference participant(s).
-     *
-     * @param conferenceParticipants The participants.
-     * @hide
-     */
-    protected final void updateConferenceParticipants(
-            List<ConferenceParticipant> conferenceParticipants) {
-        for (Listener l : mListeners) {
-            l.onConferenceParticipantsChanged(this, conferenceParticipants);
-        }
-    }
-
-    /**
-     * Notifies listeners that a conference call has been started.
-     * @hide
-     */
-    protected void notifyConferenceStarted() {
-        for (Listener l : mListeners) {
-            l.onConferenceStarted();
-        }
-    }
-
-    /**
-     * Notifies listeners when a change has occurred to the Connection which impacts its ability to
-     * be a part of a conference call.
-     * @param isConferenceSupported {@code true} if the connection supports being part of a
-     *      conference call, {@code false} otherwise.
-     * @hide
-     */
-    protected void notifyConferenceSupportedChanged(boolean isConferenceSupported) {
-        for (Listener l : mListeners) {
-            l.onConferenceSupportedChanged(this, isConferenceSupported);
-        }
-    }
-
-    /**
      * Notifies listeners when phone account is changed. For example, when the PhoneAccount is
      * changed due to an emergency call being redialed.
      * @param pHandle The new PhoneAccountHandle for this connection.
@@ -3302,10 +3238,15 @@
 
     /**
      * Sets the {@link PhoneAccountHandle} associated with this connection.
+     * <p>
+     * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount}
+     * which take place after call initiation (important for emergency calling scenarios).
      *
+     * @param phoneAccountHandle the phone account handle to set.
      * @hide
      */
-    public void setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
+    @SystemApi
+    public void setPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) {
         if (mPhoneAccountHandle != phoneAccountHandle) {
             mPhoneAccountHandle = phoneAccountHandle;
             notifyPhoneAccountChanged(phoneAccountHandle);
@@ -3314,10 +3255,16 @@
 
     /**
      * Returns the {@link PhoneAccountHandle} associated with this connection.
+     * <p>
+     * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount}
+     * which take place after call initiation (important for emergency calling scenarios).
      *
+     * @return the phone account handle specified via
+     * {@link #setPhoneAccountHandle(PhoneAccountHandle)}, or {@code null} if none was set.
      * @hide
      */
-    public PhoneAccountHandle getPhoneAccountHandle() {
+    @SystemApi
+    public @Nullable PhoneAccountHandle getPhoneAccountHandle() {
         return mPhoneAccountHandle;
     }
 
@@ -3374,9 +3321,14 @@
 
     /**
      * Sets the direction of this connection.
+     * <p>
+     * Used when calling {@link ConnectionService#addExistingConnection} to specify the existing
+     * call direction.
+     *
      * @param callDirection The direction of this connection.
      * @hide
      */
+    @SystemApi
     public void setCallDirection(@Call.Details.CallDirection int callDirection) {
         mCallDirection = callDirection;
     }
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 0cc052e..2ecdb30 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -21,7 +21,6 @@
 import android.bluetooth.BluetoothDevice;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.util.ArrayMap;
 
 import java.util.Collections;
@@ -111,6 +110,10 @@
         public void onSilenceRinger(Phone phone) { }
     }
 
+    // TODO: replace all usages of this with the actual R constant from Build.VERSION_CODES
+    /** @hide */
+    public static final int SDK_VERSION_R = 30;
+
     // A Map allows us to track each Call by its Telecom-specified call ID
     private final Map<String, Call> mCallByTelecomCallId = new ArrayMap<>();
 
@@ -143,6 +146,12 @@
     }
 
     final void internalAddCall(ParcelableCall parcelableCall) {
+        if (mTargetSdkVersion < SDK_VERSION_R
+                && parcelableCall.getState() == Call.STATE_AUDIO_PROCESSING) {
+            Log.i(this, "Skipping adding audio processing call for sdk compatibility");
+            return;
+        }
+
         Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
                 parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);
         mCallByTelecomCallId.put(parcelableCall.getId(), call);
@@ -150,7 +159,7 @@
         checkCallTree(parcelableCall);
         call.internalUpdate(parcelableCall, mCallByTelecomCallId);
         fireCallAdded(call);
-     }
+    }
 
     final void internalRemoveCall(Call call) {
         mCallByTelecomCallId.remove(call.internalGetCallId());
@@ -164,12 +173,28 @@
     }
 
     final void internalUpdateCall(ParcelableCall parcelableCall) {
-         Call call = mCallByTelecomCallId.get(parcelableCall.getId());
-         if (call != null) {
-             checkCallTree(parcelableCall);
-             call.internalUpdate(parcelableCall, mCallByTelecomCallId);
-         }
-     }
+        if (mTargetSdkVersion < SDK_VERSION_R
+                && parcelableCall.getState() == Call.STATE_AUDIO_PROCESSING) {
+            Log.i(this, "removing audio processing call during update for sdk compatibility");
+            Call call = mCallByTelecomCallId.get(parcelableCall.getId());
+            if (call != null) {
+                internalRemoveCall(call);
+            }
+            return;
+        }
+
+        Call call = mCallByTelecomCallId.get(parcelableCall.getId());
+        if (call != null) {
+            checkCallTree(parcelableCall);
+            call.internalUpdate(parcelableCall, mCallByTelecomCallId);
+        } else {
+            // This call may have come out of audio processing. Try adding it if our target sdk
+            // version is low enough.
+            if (mTargetSdkVersion < SDK_VERSION_R) {
+                internalAddCall(parcelableCall);
+            }
+        }
+    }
 
     final void internalSetPostDialWait(String telecomId, String remaining) {
         Call call = mCallByTelecomCallId.get(telecomId);
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 2bc20d5..625cd72 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -16,6 +16,7 @@
 
 import android.Manifest;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
@@ -1913,6 +1914,29 @@
         return result;
     }
 
+
+    /**
+     * Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
+     * launch the activity for emergency dialer.
+     *
+     * @param number Optional number to call in emergency dialer
+     * @hide
+     */
+    @SystemApi
+    @NonNull
+    public Intent createLaunchEmergencyDialerIntent(@Nullable String number) {
+        ITelecomService service = getTelecomService();
+        Intent result = null;
+        if (service != null) {
+            try {
+                result = service.createLaunchEmergencyDialerIntent(number);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error createLaunchEmergencyDialerIntent", e);
+            }
+        }
+        return result;
+    }
+
     /**
      * Determines whether Telecom would permit an incoming call to be added via the
      * {@link #addNewIncomingCall(PhoneAccountHandle, Bundle)} API for the specified
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 6a1b78f..2411988 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -261,6 +261,11 @@
     **/
     Intent createManageBlockedNumbersIntent();
 
+   /**
+    * @see TelecomServiceImpl#createLaunchEmergencyDialerIntent
+    */
+    Intent createLaunchEmergencyDialerIntent(in String number);
+
     /**
      * @see TelecomServiceImpl#isIncomingCallPermitted
      */
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 2236cba..2a6e8de 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -13,4 +13,5 @@
 shuoq@google.com
 refuhoo@google.com
 paulye@google.com
-nazaninb@google.com
\ No newline at end of file
+nazaninb@google.com
+sarahchin@google.com
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 9e60afc..047b220 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -526,6 +526,15 @@
             "default_vm_number_roaming_string";
 
     /**
+     * Where there is no preloaded voicemail number on a SIM card, specifies the carrier's default
+     * voicemail number while the device is both roaming and not registered for IMS.
+     * When empty string, no default voicemail number is specified for roaming network and
+     * unregistered state in IMS.
+     */
+    public static final String KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING =
+            "default_vm_number_roaming_and_ims_unregistered_string";
+
+    /**
      * Flag that specifies to use the user's own phone number as the voicemail number when there is
      * no pre-loaded voicemail number on the SIM card.
      * <p>
@@ -3232,6 +3241,7 @@
         sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
         sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
         sDefaults.putString(KEY_DEFAULT_VM_NUMBER_ROAMING_STRING, "");
+        sDefaults.putString(KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING, "");
         sDefaults.putBoolean(KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, false);
         sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
         sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true);
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 7edc91c..18687d4 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -189,11 +189,15 @@
         mTimeStamp = ts;
     }
 
-    /** @hide */
+    /**
+     * @return a {@link CellIdentity} instance.
+     */
     @NonNull
     public abstract CellIdentity getCellIdentity();
 
-    /** @hide */
+    /**
+     * @return a {@link CellSignalStrength} instance.
+     */
     @NonNull
     public abstract CellSignalStrength getCellSignalStrength();
 
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 3e02871..56b7236 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -24,8 +24,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.AccessNetworkConstants.TransportType;
-
 import android.telephony.Annotation.NetworkType;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -90,7 +90,7 @@
      * Dual Connectivity(EN-DC).
      * @hide
      */
-    public static final int NR_STATE_NONE = -1;
+    public static final int NR_STATE_NONE = 0;
 
     /**
      * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1d00b4f..f503348 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -102,7 +102,7 @@
      * Indicates frequency range is unknown.
      * @hide
      */
-    public static final int FREQUENCY_RANGE_UNKNOWN = -1;
+    public static final int FREQUENCY_RANGE_UNKNOWN = 0;
 
     /**
      * Indicates the frequency range is below 1GHz.
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 40d057f..8425ec1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -47,6 +47,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelUuid;
@@ -58,10 +59,8 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 
-import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.ISetOpportunisticDataCallback;
 import com.android.internal.telephony.ISub;
-import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.Preconditions;
 
@@ -923,20 +922,24 @@
             OnSubscriptionsChangedListenerHandler(Looper looper) {
                 super(looper);
             }
-
-            @Override
-            public void handleMessage(Message msg) {
-                if (DBG) {
-                    log("handleMessage: invoke the overriden onSubscriptionsChanged()");
-                }
-                OnSubscriptionsChangedListener.this.onSubscriptionsChanged();
-            }
         }
 
-        private final Handler mHandler;
+        /**
+         * Posted executor callback on the handler associated with a given looper.
+         * The looper can be the calling thread's looper or the looper passed from the
+         * constructor {@link #OnSubscriptionsChangedListener(Looper)}.
+         */
+        private final HandlerExecutor mExecutor;
+
+        /**
+         * @hide
+         */
+        public HandlerExecutor getHandlerExecutor() {
+            return mExecutor;
+        }
 
         public OnSubscriptionsChangedListener() {
-            mHandler = new OnSubscriptionsChangedListenerHandler();
+            mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler());
         }
 
         /**
@@ -945,7 +948,7 @@
          * @hide
          */
         public OnSubscriptionsChangedListener(Looper looper) {
-            mHandler = new OnSubscriptionsChangedListenerHandler(looper);
+            mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper));
         }
 
         /**
@@ -957,18 +960,6 @@
             if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN");
         }
 
-        /**
-         * The callback methods need to be called on the handler thread where
-         * this object was created.  If the binder did that for us it'd be nice.
-         */
-        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
-            @Override
-            public void onSubscriptionsChanged() {
-                if (DBG) log("callback: received, sendEmptyMessage(0) to handler");
-                mHandler.sendEmptyMessage(0);
-            }
-        };
-
         private void log(String s) {
             Rlog.d(LOG_TAG, s);
         }
@@ -1010,21 +1001,19 @@
      *                 onSubscriptionsChanged overridden.
      */
     public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
+        if (listener == null) return;
         String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         if (DBG) {
             logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
                     + " listener=" + listener);
         }
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available. Where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        // We use the TelephonyRegistry as it runs in the system and thus is always
+        // available. Where as SubscriptionController could crash and not be available
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,
+                    listener.mExecutor);
         }
     }
 
@@ -1036,21 +1025,18 @@
      * @param listener that is to be unregistered.
      */
     public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
+        if (listener == null) return;
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         if (DBG) {
             logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
                     + " listener=" + listener);
         }
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        // We use the TelephonyRegistry as it runs in the system and thus is always
+        // available where as SubscriptionController could crash and not be available
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener);
         }
     }
 
@@ -1069,7 +1055,6 @@
      * for #onOpportunisticSubscriptionsChanged to be invoked.
      */
     public static class OnOpportunisticSubscriptionsChangedListener {
-        private Executor mExecutor;
         /**
          * Callback invoked when there is any change to any SubscriptionInfo. Typically
          * this method would invoke {@link #getActiveSubscriptionInfoList}
@@ -1078,27 +1063,6 @@
             if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN");
         }
 
-        private void setExecutor(Executor executor) {
-            mExecutor = executor;
-        }
-
-        /**
-         * The callback methods need to be called on the handler thread where
-         * this object was created.  If the binder did that for us it'd be nice.
-         */
-        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
-            @Override
-            public void onSubscriptionsChanged() {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    if (DBG) log("onOpportunisticSubscriptionsChanged callback received.");
-                    mExecutor.execute(() -> onOpportunisticSubscriptionsChanged());
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-        };
-
         private void log(String s) {
             Rlog.d(LOG_TAG, s);
         }
@@ -1125,18 +1089,13 @@
                     + " listener=" + listener);
         }
 
-        listener.setExecutor(executor);
-
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available. Where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.addOnOpportunisticSubscriptionsChangedListener(pkgName, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        // We use the TelephonyRegistry as it runs in the system and thus is always
+        // available where as SubscriptionController could crash and not be available
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener(
+                    listener, executor);
         }
     }
 
@@ -1156,16 +1115,10 @@
             logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug="
                     + pkgForDebug + " listener=" + listener);
         }
-        try {
-            // We use the TelephonyRegistry as it runs in the system and thus is always
-            // available where as SubscriptionController could crash and not be available
-            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                    "telephony.registry"));
-            if (tr != null) {
-                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
-            }
-        } catch (RemoteException ex) {
-            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
+        TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistryManager != null) {
+            telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener);
         }
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 03e57e7..2eb4809 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -424,18 +424,8 @@
      * {@link #getActiveModemCount} returns 1 while this API returns 2.
      */
     public @ModemCount int getSupportedModemCount() {
-        // TODO: b/139642279 when turning on this feature, remove dependency of
-        // PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE and always return result based on
-        // PROPERTY_MAX_ACTIVE_MODEMS.
-        String rebootRequired = SystemProperties.get(
-                TelephonyProperties.PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE);
-        if (rebootRequired.equals("false")) {
-            // If no reboot is required, return max possible active modems.
-            return SystemProperties.getInt(
-                    TelephonyProperties.PROPERTY_MAX_ACTIVE_MODEMS, getPhoneCount());
-        } else {
-            return getPhoneCount();
-        }
+        return SystemProperties.getInt(TelephonyProperties.PROPERTY_MAX_ACTIVE_MODEMS,
+                getActiveModemCount());
     }
 
     /** {@hide} */
@@ -1619,12 +1609,11 @@
      * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
-     *
-     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * <p>
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
      */
-    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @Nullable
     public String getDeviceSoftwareVersion() {
         return getDeviceSoftwareVersion(getSlotIndex());
     }
@@ -1633,12 +1622,16 @@
      * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
+     * <p>
+     * Requires Permission: READ_PRIVILEGED_PHONE_STATE.
      *
      * @param slotIndex of which deviceID is returned
+     *
+     * @hide
      */
-    /** {@hide} */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @Nullable
     public String getDeviceSoftwareVersion(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -10234,11 +10227,13 @@
 
     /**
      * Action set from carrier signalling broadcast receivers to enable/disable radio
-     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+     * Permissions {@link android.Manifest.permission.MODIFY_PHONE_STATE} is required.
      * @param subId the subscription ID that this action applies to.
      * @param enabled control enable or disable radio.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
         try {
             ITelephony service = getITelephony();
@@ -10253,11 +10248,13 @@
     /**
      * Action set from carrier signalling broadcast receivers to start/stop reporting default
      * network available events
-     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+     * Permissions {@link android.Manifest.permission.MODIFY_PHONE_STATE} is required.
      * @param subId the subscription ID that this action applies to.
      * @param report control start/stop reporting network status.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
         try {
             ITelephony service = getITelephony();
@@ -10271,10 +10268,12 @@
 
     /**
      * Action set from carrier signalling broadcast receivers to reset all carrier actions
-     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+     * Permissions {@link android.Manifest.permission.MODIFY_PHONE_STATE} is required.
      * @param subId the subscription ID that this action applies to.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void carrierActionResetAll(int subId) {
         try {
             ITelephony service = getITelephony();
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 5a90cb1..0025c7a 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -830,7 +830,7 @@
      * @param callbackIntent a PendingIntent to launch when the operation completes.
      *
      * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase
-     * and use @link{eraseSubscriptionsWithOptions} instead
+     * and use {@link #eraseSubscriptionsWithOptions(int, PendingIntent)} instead
      *
      * @hide
      */
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 39e00cc..f79a5c6 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1778,21 +1778,6 @@
      boolean isInEmergencySmsMode();
 
     /**
-     * Get a list of SMS apps on a user.
-     */
-    String[] getSmsApps(int userId);
-
-    /**
-     * Get the default SMS app on a given user.
-     */
-    String getDefaultSmsApp(int userId);
-
-    /**
-     * Set the default SMS app to a given package on a given user.
-     */
-    void setDefaultSmsApp(int userId, String packageName);
-
-    /**
      * Return the modem radio power state for slot index.
      *
      */
diff --git a/tests/BootImageProfileTest/AndroidTest.xml b/tests/BootImageProfileTest/AndroidTest.xml
index c132007..b4f2663 100644
--- a/tests/BootImageProfileTest/AndroidTest.xml
+++ b/tests/BootImageProfileTest/AndroidTest.xml
@@ -22,8 +22,8 @@
         <!-- we need this magic flag, otherwise it always reboots and breaks the selinux -->
         <option name="force-skip-system-props" value="true" />
 
-        <option name="run-command" value="setprop dalvik.vm.profilesystemserver true" />
-        <option name="run-command" value="setprop dalvik.vm.profilebootclasspath true" />
+        <option name="run-command" value="device_config put runtime_native_boot profilesystemserver true" />
+        <option name="run-command" value="device_config put runtime_native_boot profilebootclasspath true" />
 
         <!-- Profiling does not pick up the above changes we restart the shell -->
         <option name="run-command" value="stop" />
diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
index fe1d9d2..81937e6 100644
--- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
+++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
@@ -46,17 +46,23 @@
      */
     @Test
     public void testProperties() throws Exception {
-        String res = mTestDevice.getProperty("dalvik.vm.profilebootclasspath");
+        String res = mTestDevice.getProperty(
+                "persist.device_config.runtime_native_boot.profilebootclasspath");
         assertTrue("profile boot class path not enabled", res != null && res.equals("true"));
-        res = mTestDevice.getProperty("dalvik.vm.profilesystemserver");
+        res = mTestDevice.getProperty(
+                "persist.device_config.runtime_native_boot.profilesystemserver");
         assertTrue("profile system server not enabled", res != null && res.equals("true"));
     }
 
-    private void forceSaveProfile(String pkg) throws Exception {
+    private boolean forceSaveProfile(String pkg) throws Exception {
         String pid = mTestDevice.executeShellCommand("pidof " + pkg).trim();
-        assertTrue("Invalid pid " + pid, pid.length() > 0);
+        if (pid.length() == 0) {
+            // Not yet running.
+            return false;
+        }
         String res = mTestDevice.executeShellCommand("kill -s SIGUSR1 " + pid).trim();
         assertTrue("kill SIGUSR1: " + res, res.length() == 0);
+        return true;
     }
 
     @Test
@@ -69,10 +75,13 @@
         // Wait up to 20 seconds for the profile to be saved.
         for (int i = 0; i < 20; ++i) {
             // Force save the profile since we truncated it.
-            forceSaveProfile("system_server");
-            String s = mTestDevice.executeShellCommand("wc -c <" + SYSTEM_SERVER_PROFILE).trim();
-            if (!"0".equals(s)) {
-                break;
+            if (forceSaveProfile("system_server")) {
+                // Might fail if system server is not yet running.
+                String s = mTestDevice.executeShellCommand(
+                        "wc -c <" + SYSTEM_SERVER_PROFILE).trim();
+                if (!"0".equals(s)) {
+                    break;
+                }
             }
             Thread.sleep(1000);
         }
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
index 3515053..325c1c0 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -32,7 +32,7 @@
 
 
 
-    // Code below generated by codegen v1.0.8.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -58,7 +58,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(android.os.Parcel dest, int flags) {
+    public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -72,7 +72,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected HierrarchicalDataClassBase(android.os.Parcel in) {
+    protected HierrarchicalDataClassBase(@android.annotation.NonNull android.os.Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -92,14 +92,14 @@
         }
 
         @Override
-        public HierrarchicalDataClassBase createFromParcel(android.os.Parcel in) {
+        public HierrarchicalDataClassBase createFromParcel(@android.annotation.NonNull android.os.Parcel in) {
             return new HierrarchicalDataClassBase(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1570828332402L,
-            codegenVersion = "1.0.8",
+            time = 1571258914826L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java",
             inputSignatures = "private  int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
index c867409..6c92009 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -46,7 +46,7 @@
 
 
 
-    // Code below generated by codegen v1.0.8.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -74,7 +74,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(android.os.Parcel dest, int flags) {
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -90,7 +90,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected HierrarchicalDataClassChild(android.os.Parcel in) {
+    protected HierrarchicalDataClassChild(@NonNull android.os.Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -114,14 +114,14 @@
         }
 
         @Override
-        public HierrarchicalDataClassChild createFromParcel(android.os.Parcel in) {
+        public HierrarchicalDataClassChild createFromParcel(@NonNull android.os.Parcel in) {
             return new HierrarchicalDataClassChild(in);
         }
     };
 
     @DataClass.Generated(
-            time = 1570828333399L,
-            codegenVersion = "1.0.8",
+            time = 1571258915848L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java",
             inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
index 8d097a0..36def8a 100644
--- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -52,7 +52,7 @@
 
 
 
-    // Code below generated by codegen v1.0.8.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -161,7 +161,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -185,7 +185,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected ParcelAllTheThingsDataClass(Parcel in) {
+    protected ParcelAllTheThingsDataClass(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -237,7 +237,7 @@
         }
 
         @Override
-        public ParcelAllTheThingsDataClass createFromParcel(Parcel in) {
+        public ParcelAllTheThingsDataClass createFromParcel(@NonNull Parcel in) {
             return new ParcelAllTheThingsDataClass(in);
         }
     };
@@ -410,8 +410,8 @@
     }
 
     @DataClass.Generated(
-            time = 1570828331396L,
-            codegenVersion = "1.0.8",
+            time = 1571258913802L,
+            codegenVersion = "1.0.9",
             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\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
     @Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index d014d6d..c444d61 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.8.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -1119,7 +1119,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public boolean equals(Object o) {
+    public boolean equals(@Nullable Object o) {
         // You can override field equality logic by defining either of the methods like:
         // boolean fieldNameEquals(SampleDataClass other) { ... }
         // boolean fieldNameEquals(FieldType otherValue) { ... }
@@ -1184,8 +1184,8 @@
 
     @DataClass.Generated.Member
     void forEachField(
-            DataClass.PerIntFieldAction<SampleDataClass> actionInt,
-            DataClass.PerObjectFieldAction<SampleDataClass> actionObject) {
+            @NonNull DataClass.PerIntFieldAction<SampleDataClass> actionInt,
+            @NonNull DataClass.PerObjectFieldAction<SampleDataClass> actionObject) {
         actionInt.acceptInt(this, "num", mNum);
         actionInt.acceptInt(this, "num2", mNum2);
         actionInt.acceptInt(this, "num4", mNum4);
@@ -1211,7 +1211,7 @@
     /** @deprecated May cause boxing allocations - use with caution! */
     @Deprecated
     @DataClass.Generated.Member
-    void forEachField(DataClass.PerObjectFieldAction<SampleDataClass> action) {
+    void forEachField(@NonNull DataClass.PerObjectFieldAction<SampleDataClass> action) {
         action.acceptObject(this, "num", mNum);
         action.acceptObject(this, "num2", mNum2);
         action.acceptObject(this, "num4", mNum4);
@@ -1258,7 +1258,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -1297,7 +1297,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    /* package-private */ SampleDataClass(Parcel in) {
+    /* package-private */ SampleDataClass(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -1420,7 +1420,7 @@
         }
 
         @Override
-        public SampleDataClass createFromParcel(Parcel in) {
+        public SampleDataClass createFromParcel(@NonNull Parcel in) {
             return new SampleDataClass(in);
         }
     };
@@ -1872,8 +1872,8 @@
     }
 
     @DataClass.Generated(
-            time = 1570828329319L,
-            codegenVersion = "1.0.8",
+            time = 1571258911688L,
+            codegenVersion = "1.0.9",
             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/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index 1c87e8f..55feae7 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -85,7 +85,7 @@
 
 
 
-    // Code below generated by codegen v1.0.8.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -142,7 +142,7 @@
 
     @Override
     @DataClass.Generated.Member
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
@@ -158,7 +158,7 @@
     /** @hide */
     @SuppressWarnings({"unchecked", "RedundantCast"})
     @DataClass.Generated.Member
-    protected SampleWithCustomBuilder(Parcel in) {
+    protected SampleWithCustomBuilder(@NonNull Parcel in) {
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
@@ -184,7 +184,7 @@
         }
 
         @Override
-        public SampleWithCustomBuilder createFromParcel(Parcel in) {
+        public SampleWithCustomBuilder createFromParcel(@NonNull Parcel in) {
             return new SampleWithCustomBuilder(in);
         }
     };
@@ -253,8 +253,8 @@
     }
 
     @DataClass.Generated(
-            time = 1570828330331L,
-            codegenVersion = "1.0.8",
+            time = 1571258912752L,
+            codegenVersion = "1.0.9",
             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\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
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
index 27af37f..b967f19 100644
--- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
@@ -51,7 +51,7 @@
 
 
 
-    // Code below generated by codegen v1.0.8.
+    // Code below generated by codegen v1.0.9.
     //
     // DO NOT MODIFY!
     // CHECKSTYLE:OFF Generated code
@@ -65,8 +65,8 @@
 
 
     @DataClass.Generated(
-            time = 1570828334384L,
-            codegenVersion = "1.0.8",
+            time = 1571258916868L,
+            codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java",
             inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)")
     @Deprecated
diff --git a/tests/Compatibility/Android.bp b/tests/Compatibility/Android.bp
index 4ca406e..7dc44fa 100644
--- a/tests/Compatibility/Android.bp
+++ b/tests/Compatibility/Android.bp
@@ -19,4 +19,7 @@
     srcs: ["src/**/*.java"],
     platform_apis: true,
     certificate: "platform",
+    test_suites: [
+        "csuite"
+    ],
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index ed8f272..599ee56 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -33,6 +33,7 @@
 import android.content.IntentFilter;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
+import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.util.Log;
 
@@ -52,7 +53,9 @@
 import org.junit.runners.JUnit4;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * Test system Rollback APIs.
@@ -96,7 +99,10 @@
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
                     Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.MANAGE_USERS,
+                    Manifest.permission.CREATE_USERS,
+                    Manifest.permission.INTERACT_ACROSS_USERS);
 
             // Register a broadcast receiver for notification when the
             // rollback has been committed.
@@ -106,7 +112,6 @@
             // Uninstall TestApp.A
             Uninstall.packages(TestApp.A);
             assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
-
             // TODO: There is currently a race condition between when the app is
             // uninstalled and when rollback manager deletes the rollback. Fix it
             // so that's not the case!
@@ -149,6 +154,12 @@
             RollbackUtils.rollback(available.getRollbackId());
             assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
 
+            UserManager um = (UserManager) context.getSystemService(context.USER_SERVICE);
+            List<Integer> userIds = um.getUsers(true)
+                    .stream().map(user -> user.id).collect(Collectors.toList());
+            assertThat(InstallUtils.isOnlyInstalledForUser(TestApp.A,
+                    context.getUserId(), userIds)).isTrue();
+
             // Verify we received a broadcast for the rollback.
             // TODO: Race condition between the timeout and when the broadcast is
             // received could lead to test flakiness.
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 8b97f61..b51aad1 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -32,6 +32,8 @@
 import android.content.pm.PackageInstaller;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
+import android.os.ParcelFileDescriptor;
+import android.provider.DeviceConfig;
 import android.text.TextUtils;
 
 import androidx.test.InstrumentationRegistry;
@@ -45,12 +47,16 @@
 import com.android.cts.rollback.lib.RollbackUtils;
 import com.android.internal.R;
 
+import libcore.io.IoUtils;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Tests for rollback of staged installs.
  * <p>
@@ -64,6 +70,8 @@
 
     private static final String NETWORK_STACK_CONNECTOR_CLASS =
             "android.net.INetworkStackConnector";
+    private static final String PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT =
+            "watchdog_trigger_failure_count";
 
     private static final String MODULE_META_DATA_PACKAGE = getModuleMetadataPackageName();
 
@@ -76,7 +84,8 @@
                 Manifest.permission.INSTALL_PACKAGES,
                 Manifest.permission.DELETE_PACKAGES,
                 Manifest.permission.TEST_MANAGE_ROLLBACKS,
-                Manifest.permission.FORCE_STOP_PACKAGES);
+                Manifest.permission.FORCE_STOP_PACKAGES,
+                Manifest.permission.WRITE_DEVICE_CONFIG);
     }
 
     /**
@@ -119,6 +128,13 @@
         assertThat(rollback).packagesContainsExactly(
                 Rollback.from(TestApp.A2).to(TestApp.A1));
         assertThat(rollback.isStaged()).isTrue();
+
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+                PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
+                Integer.toString(5), false);
+        RollbackUtils.sendCrashBroadcast(TestApp.A, 4);
+        // Sleep for a while to make sure we don't trigger rollback
+        Thread.sleep(TimeUnit.SECONDS.toMillis(30));
     }
 
     /**
@@ -128,8 +144,8 @@
      */
     @Test
     public void testBadApkOnly_Phase3() throws Exception {
-        // Crash TestApp.A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback
-        RollbackUtils.sendCrashBroadcast(TestApp.A, 5);
+        // One more crash to trigger rollback
+        RollbackUtils.sendCrashBroadcast(TestApp.A, 1);
 
         // We expect the device to be rebooted automatically. Wait for that to happen.
         Thread.sleep(30 * 1000);
@@ -158,18 +174,6 @@
         assertThat(rollback.getCommittedSessionId()).isNotEqualTo(-1);
     }
 
-    @Test
-    public void resetNetworkStack() throws Exception {
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        String networkStack = getNetworkStackPackageName();
-
-        rm.expireRollbackForPackage(networkStack);
-        Uninstall.packages(networkStack);
-
-        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
-                        networkStack)).isNull();
-    }
-
     /**
      * Stage install ModuleMetadata package to simulate a Mainline module update.
      */
@@ -209,26 +213,38 @@
     }
 
     @Test
-    public void assertNetworkStackRollbackAvailable() throws Exception {
+    public void testNetworkFailedRollback_Phase1() throws Exception {
+        RollbackManager rm = RollbackUtils.getRollbackManager();
+        String networkStack = getNetworkStackPackageName();
+
+        rm.expireRollbackForPackage(networkStack);
+        uninstallNetworkStackPackage();
+
+        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
+                        networkStack)).isNull();
+    }
+
+    @Test
+    public void testNetworkFailedRollback_Phase2() throws Exception {
         RollbackManager rm = RollbackUtils.getRollbackManager();
         assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
                         getNetworkStackPackageName())).isNotNull();
     }
 
     @Test
-    public void assertNetworkStackRollbackCommitted() throws Exception {
-        RollbackManager rm = RollbackUtils.getRollbackManager();
-        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
-                        getNetworkStackPackageName())).isNotNull();
-    }
-
-    @Test
-    public void assertNoNetworkStackRollbackCommitted() throws Exception {
+    public void testNetworkFailedRollback_Phase3() throws Exception {
         RollbackManager rm = RollbackUtils.getRollbackManager();
         assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
                         getNetworkStackPackageName())).isNull();
     }
 
+    @Test
+    public void testNetworkFailedRollback_Phase4() throws Exception {
+        RollbackManager rm = RollbackUtils.getRollbackManager();
+        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
+                        getNetworkStackPackageName())).isNotNull();
+    }
+
     private String getNetworkStackPackageName() {
         Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
         ComponentName comp = intent.resolveSystemService(
@@ -236,8 +252,14 @@
         return comp.getPackageName();
     }
 
+    private void uninstallNetworkStackPackage() {
+        // Since the host side use shell command to install the network stack package, uninstall
+        // must be done by shell command as well. Otherwise uninstall by a different user will fail.
+        runShellCommand("pm uninstall " + getNetworkStackPackageName());
+    }
+
     @Test
-    public void testPreviouslyAbandonedRollbacksEnableRollback() throws Exception {
+    public void testPreviouslyAbandonedRollbacks_Phase1() throws Exception {
         Uninstall.packages(TestApp.A);
         Install.single(TestApp.A1).commit();
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
@@ -255,7 +277,7 @@
     }
 
     @Test
-    public void testPreviouslyAbandonedRollbacksCommitRollback() throws Exception {
+    public void testPreviouslyAbandonedRollbacks_Phase2() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
         InstallUtils.processUserData(TestApp.A);
 
@@ -266,12 +288,38 @@
     }
 
     @Test
-    public void testPreviouslyAbandonedRollbacksCheckUserdataRollback() throws Exception {
+    public void testPreviouslyAbandonedRollbacks_Phase3() throws Exception {
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
         InstallUtils.processUserData(TestApp.A);
         Uninstall.packages(TestApp.A);
     }
 
+    @Test
+    public void testNetworkPassedDoesNotRollback_Phase1() throws Exception {
+        RollbackManager rm = RollbackUtils.getRollbackManager();
+        String networkStack = getNetworkStackPackageName();
+
+        rm.expireRollbackForPackage(networkStack);
+        uninstallNetworkStackPackage();
+
+        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
+                        networkStack)).isNull();
+    }
+
+    @Test
+    public void testNetworkPassedDoesNotRollback_Phase2() throws Exception {
+        RollbackManager rm = RollbackUtils.getRollbackManager();
+        assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
+                        getNetworkStackPackageName())).isNotNull();
+    }
+
+    @Test
+    public void testNetworkPassedDoesNotRollback_Phase3() throws Exception {
+        RollbackManager rm = RollbackUtils.getRollbackManager();
+        assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
+                        getNetworkStackPackageName())).isNull();
+    }
+
     @Nullable
     private static String getModuleMetadataPackageName() {
         String packageName = InstrumentationRegistry.getContext().getResources().getString(
@@ -293,7 +341,8 @@
     }
 
     private void runShellCommand(String cmd) {
-        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+        ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .executeShellCommand(cmd);
+        IoUtils.closeQuietly(pfd);
     }
 }
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 2043027..f7fe6c7 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -94,7 +94,6 @@
 
         // Reboot device to activate staged package
         getDevice().reboot();
-        getDevice().waitForDeviceAvailable();
 
         runPhase("testNativeWatchdogTriggersRollback_Phase2");
 
@@ -122,7 +121,7 @@
     @Test
     public void testNetworkFailedRollback() throws Exception {
         // Remove available rollbacks and uninstall NetworkStack on /data/
-        runPhase("resetNetworkStack");
+        runPhase("testNetworkFailedRollback_Phase1");
         // Reduce health check deadline
         getDevice().executeShellCommand("device_config put rollback "
                 + "watchdog_request_timeout_millis 300000");
@@ -134,20 +133,19 @@
         Thread.sleep(5000);
         // Reboot device to activate staged package
         getDevice().reboot();
-        getDevice().waitForDeviceAvailable();
 
         // Verify rollback was enabled
-        runPhase("assertNetworkStackRollbackAvailable");
+        runPhase("testNetworkFailedRollback_Phase2");
 
         // Sleep for < health check deadline
         Thread.sleep(5000);
         // Verify rollback was not executed before health check deadline
-        runPhase("assertNoNetworkStackRollbackCommitted");
+        runPhase("testNetworkFailedRollback_Phase3");
         try {
             // This is expected to fail due to the device being rebooted out
             // from underneath the test. If this fails for reasons other than
             // the device reboot, those failures should result in failure of
-            // the assertNetworkStackExecutedRollback phase.
+            // the testNetworkFailedRollback_Phase4 phase.
             CLog.logAndDisplay(LogLevel.INFO, "Sleep and expect to fail while sleeping");
             // Sleep for > health check deadline
             Thread.sleep(260000);
@@ -157,7 +155,7 @@
 
         getDevice().waitForDeviceAvailable();
         // Verify rollback was executed after health check deadline
-        runPhase("assertNetworkStackRollbackCommitted");
+        runPhase("testNetworkFailedRollback_Phase4");
     }
 
     /**
@@ -166,7 +164,7 @@
     @Test
     public void testNetworkPassedDoesNotRollback() throws Exception {
         // Remove available rollbacks and uninstall NetworkStack on /data/
-        runPhase("resetNetworkStack");
+        runPhase("testNetworkPassedDoesNotRollback_Phase1");
         // Reduce health check deadline, here unlike the network failed case, we use
         // a longer deadline because joining a network can take a much longer time for
         // reasons external to the device than 'not joining'
@@ -180,10 +178,9 @@
         Thread.sleep(5000);
         // Reboot device to activate staged package
         getDevice().reboot();
-        getDevice().waitForDeviceAvailable();
 
         // Verify rollback was enabled
-        runPhase("assertNetworkStackRollbackAvailable");
+        runPhase("testNetworkPassedDoesNotRollback_Phase2");
 
         // Connect to internet so network health check passes
         getDevice().executeShellCommand("svc wifi enable");
@@ -196,7 +193,7 @@
         // Sleep for > health check deadline
         Thread.sleep(310000);
         // Verify rollback was not executed after health check deadline
-        runPhase("assertNoNetworkStackRollbackCommitted");
+        runPhase("testNetworkPassedDoesNotRollback_Phase3");
     }
 
     /**
@@ -204,11 +201,11 @@
      */
     @Test
     public void testPreviouslyAbandonedRollbacks() throws Exception {
-        runPhase("testPreviouslyAbandonedRollbacksEnableRollback");
+        runPhase("testPreviouslyAbandonedRollbacks_Phase1");
         getDevice().reboot();
-        runPhase("testPreviouslyAbandonedRollbacksCommitRollback");
+        runPhase("testPreviouslyAbandonedRollbacks_Phase2");
         getDevice().reboot();
-        runPhase("testPreviouslyAbandonedRollbacksCheckUserdataRollback");
+        runPhase("testPreviouslyAbandonedRollbacks_Phase3");
     }
 
     private void crashProcess(String processName, int numberOfCrashes) throws Exception {
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
index 7d9d0d5..7e8a134 100644
--- a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -30,6 +30,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.usage.IntervalStats;
+import com.android.server.usage.PackagesTokenData;
 import com.android.server.usage.UsageStatsDatabase;
 import com.android.server.usage.UsageStatsDatabase.StatCombiner;
 
@@ -79,6 +80,7 @@
         sContext = InstrumentationRegistry.getTargetContext();
         mTestDir = new File(sContext.getFilesDir(), "UsageStatsDatabasePerfTest");
         sUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
+        sUsageStatsDatabase.readMappingsLocked();
         sUsageStatsDatabase.init(1);
     }
 
@@ -140,6 +142,37 @@
         }
     }
 
+    private void runObfuscateStatsTest(int packageCount, int eventsPerPackage) {
+        final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
+        IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
+        long elapsedTimeNs = 0;
+        while (benchmarkState.keepRunning(elapsedTimeNs)) {
+            final long startTime = SystemClock.elapsedRealtimeNanos();
+            PackagesTokenData packagesTokenData = new PackagesTokenData();
+            intervalStats.obfuscateData(packagesTokenData);
+            final long endTime = SystemClock.elapsedRealtimeNanos();
+            elapsedTimeNs = endTime - startTime;
+            clearUsageStatsFiles();
+        }
+    }
+
+    private void runDeobfuscateStatsTest(int packageCount, int eventsPerPackage) {
+        final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
+        IntervalStats intervalStats = new IntervalStats();
+        populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
+        long elapsedTimeNs = 0;
+        while (benchmarkState.keepRunning(elapsedTimeNs)) {
+            PackagesTokenData packagesTokenData = new PackagesTokenData();
+            intervalStats.obfuscateData(packagesTokenData);
+            final long startTime = SystemClock.elapsedRealtimeNanos();
+            intervalStats.deobfuscateData(packagesTokenData);
+            final long endTime = SystemClock.elapsedRealtimeNanos();
+            elapsedTimeNs = endTime - startTime;
+            clearUsageStatsFiles();
+        }
+    }
+
     @Test
     public void testQueryUsageStats_FewPkgsLightUse() throws IOException {
         runQueryUsageStatsTest(FEW_PKGS, LIGHT_USE);
@@ -151,6 +184,16 @@
     }
 
     @Test
+    public void testObfuscateStats_FewPkgsLightUse() {
+        runObfuscateStatsTest(FEW_PKGS, LIGHT_USE);
+    }
+
+    @Test
+    public void testDeobfuscateStats_FewPkgsLightUse() {
+        runDeobfuscateStatsTest(FEW_PKGS, LIGHT_USE);
+    }
+
+    @Test
     public void testQueryUsageStats_FewPkgsHeavyUse() throws IOException {
         runQueryUsageStatsTest(FEW_PKGS, HEAVY_USE);
     }
@@ -161,6 +204,16 @@
     }
 
     @Test
+    public void testObfuscateStats_FewPkgsHeavyUse() {
+        runObfuscateStatsTest(FEW_PKGS, HEAVY_USE);
+    }
+
+    @Test
+    public void testDeobfuscateStats_FewPkgsHeavyUse() {
+        runDeobfuscateStatsTest(FEW_PKGS, HEAVY_USE);
+    }
+
+    @Test
     public void testQueryUsageStats_ManyPkgsLightUse() throws IOException {
         runQueryUsageStatsTest(MANY_PKGS, LIGHT_USE);
     }
@@ -171,6 +224,16 @@
     }
 
     @Test
+    public void testObfuscateStats_ManyPkgsLightUse() {
+        runObfuscateStatsTest(MANY_PKGS, LIGHT_USE);
+    }
+
+    @Test
+    public void testDeobfuscateStats_ManyPkgsLightUse() {
+        runDeobfuscateStatsTest(MANY_PKGS, LIGHT_USE);
+    }
+
+    @Test
     public void testQueryUsageStats_ManyPkgsHeavyUse() throws IOException {
         runQueryUsageStatsTest(MANY_PKGS, HEAVY_USE);
     }
@@ -179,4 +242,14 @@
     public void testPutUsageStats_ManyPkgsHeavyUse() throws IOException {
         runPutUsageStatsTest(MANY_PKGS, HEAVY_USE);
     }
+
+    @Test
+    public void testObfuscateStats_ManyPkgsHeavyUse() {
+        runObfuscateStatsTest(MANY_PKGS, HEAVY_USE);
+    }
+
+    @Test
+    public void testDeobfuscateStats_ManyPkgsHeavyUse() {
+        runDeobfuscateStatsTest(MANY_PKGS, HEAVY_USE);
+    }
 }
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index e91abb6..b9b2238 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -5,7 +5,6 @@
     name: "FrameworksNetTests-jni-defaults",
     jni_libs: [
         "ld-android",
-        "libartbase",
         "libbacktrace",
         "libbase",
         "libbinder",
@@ -16,7 +15,6 @@
         "libcgrouprc",
         "libcrypto",
         "libcutils",
-        "libdexfile",
         "libdl_android",
         "libhidl-gen-utils",
         "libhidlbase",
@@ -46,7 +44,11 @@
 android_test {
     name: "FrameworksNetTests",
     defaults: ["FrameworksNetTests-jni-defaults"],
-    srcs: ["java/**/*.java", "java/**/*.kt"],
+    srcs: [
+        ":tethering-tests-src",
+        "java/**/*.java",
+        "java/**/*.kt",
+    ],
     platform_apis: true,
     test_suites: ["device-tests"],
     certificate: "platform",
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 2ca0d1a..1569112 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -271,7 +271,7 @@
             .addCapability(NET_CAPABILITY_NOT_METERED);
         assertParcelingIsLossless(netCap);
         netCap.setSSID(TEST_SSID);
-        assertParcelSane(netCap, 11);
+        assertParcelSane(netCap, 12);
     }
 
     @Test
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
index 46e27c1..1f2bb0a 100644
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
@@ -30,6 +30,7 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.app.Instrumentation;
 import android.content.Context;
@@ -283,6 +284,107 @@
         assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
     }
 
+    // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO.
+    private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX =
+            // struct nlmsghdr
+            "48000000" +     // length = 72
+            "1400" +         // type = SOCK_DIAG_BY_FAMILY
+            "0100" +         // flags = NLM_F_REQUEST
+            "00000000" +     // seqno
+            "00000000" +     // pid (0 == kernel)
+            // struct inet_diag_req_v2
+            "02" +           // family = AF_INET
+            "06" +           // protcol = IPPROTO_TCP
+            "02" +           // idiag_ext = INET_DIAG_INFO
+            "00" +           // pad
+            "ffffffff" +   // idiag_states
+            // inet_diag_sockid
+            "3039" +         // idiag_sport = 12345
+            "d431" +         // idiag_dport = 54321
+            "01020304000000000000000000000000" + // idiag_src = 1.2.3.4
+            "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4
+            "00000000" +     // idiag_if
+            "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
+
+    private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES =
+            HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false);
+    private static final int TCP_ALL_STATES = 0xffffffff;
+    @Test
+    public void testInetDiagReqV2TcpInetWithExt() throws Exception {
+        InetSocketAddress local = new InetSocketAddress(
+                InetAddress.getByName("1.2.3.4"), 12345);
+        InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
+                54321);
+        byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET,
+                NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES);
+
+        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg);
+
+        local = new InetSocketAddress(
+                InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
+        remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
+                47473);
+        msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
+                NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+
+        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
+    }
+
+    // Hexadecimal representation of InetDiagReqV2 request with no socket specified.
+    private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX =
+            // struct nlmsghdr
+            "48000000" +     // length = 72
+            "1400" +         // type = SOCK_DIAG_BY_FAMILY
+            "0100" +         // flags = NLM_F_REQUEST
+            "00000000" +     // seqno
+            "00000000" +     // pid (0 == kernel)
+            // struct inet_diag_req_v2
+            "0a" +           // family = AF_INET6
+            "06" +           // protcol = IPPROTO_TCP
+            "00" +           // idiag_ext
+            "00" +           // pad
+            "ffffffff" +     // idiag_states
+            // inet_diag_sockid
+            "0000" +         // idiag_sport
+            "0000" +         // idiag_dport
+            "00000000000000000000000000000000" + // idiag_src
+            "00000000000000000000000000000000" + // idiag_dst
+            "00000000" +     // idiag_if
+            "0000000000000000"; // idiag_cookie
+
+    private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES =
+            HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false);
+
+    @Test
+    public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception {
+        InetSocketAddress local = new InetSocketAddress(
+                InetAddress.getByName("fe80::fe6a:ed4b"), 12345);
+        InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
+                54321);
+        // Verify no socket specified if either local or remote socket address is null.
+        byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
+                NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+        byte[] msg;
+        try {
+            msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6,
+                    NLM_F_REQUEST);
+            fail("Both remote and local should be null, expected UnknownHostException");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6,
+                    NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+            fail("Both remote and local should be null, expected UnknownHostException");
+        } catch (NullPointerException e) {
+        }
+
+        msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
+                NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg);
+        assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt);
+    }
+
     // Hexadecimal representation of InetDiagReqV2 request.
     private static final String INET_DIAG_MSG_HEX =
             // struct nlmsghdr
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index cf3fba8..61f37fd 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -33,6 +33,7 @@
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
+import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
 import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
@@ -492,6 +493,8 @@
         private INetworkMonitor mNetworkMonitor;
         private INetworkMonitorCallbacks mNmCallbacks;
         private int mNmValidationResult = VALIDATION_RESULT_BASE;
+        private int mProbesCompleted;
+        private int mProbesSucceeded;
         private String mNmValidationRedirectUrl = null;
         private boolean mNmProvNotificationRequested = false;
 
@@ -559,6 +562,7 @@
                 mNmProvNotificationRequested = false;
             }
 
+            mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
             mNmCallbacks.notifyNetworkTested(
                     mNmValidationResult, mNmValidationRedirectUrl);
 
@@ -581,7 +585,7 @@
          * @param validated Indicate if network should pretend to be validated.
          */
         public void connect(boolean validated) {
-            connect(validated, true);
+            connect(validated, true, false /* isStrictMode */);
         }
 
         /**
@@ -589,13 +593,13 @@
          * @param validated Indicate if network should pretend to be validated.
          * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
          */
-        public void connect(boolean validated, boolean hasInternet) {
+        public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
             assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
 
             ConnectivityManager.NetworkCallback callback = null;
             final ConditionVariable validatedCv = new ConditionVariable();
             if (validated) {
-                setNetworkValid();
+                setNetworkValid(isStrictMode);
                 NetworkRequest request = new NetworkRequest.Builder()
                         .addTransportType(getNetworkCapabilities().getTransportTypes()[0])
                         .clearCapabilities()
@@ -620,15 +624,15 @@
             if (validated) {
                 // Wait for network to validate.
                 waitFor(validatedCv);
-                setNetworkInvalid();
+                setNetworkInvalid(isStrictMode);
             }
 
             if (callback != null) mCm.unregisterNetworkCallback(callback);
         }
 
-        public void connectWithCaptivePortal(String redirectUrl) {
-            setNetworkPortal(redirectUrl);
-            connect(false);
+        public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
+            setNetworkPortal(redirectUrl, isStrictMode);
+            connect(false, true /* hasInternet */, isStrictMode);
         }
 
         public void connectWithPartialConnectivity() {
@@ -636,34 +640,75 @@
             connect(false);
         }
 
-        public void connectWithPartialValidConnectivity() {
-            setNetworkPartialValid();
-            connect(false);
+        public void connectWithPartialValidConnectivity(boolean isStrictMode) {
+            setNetworkPartialValid(isStrictMode);
+            connect(false, true /* hasInternet */, isStrictMode);
         }
 
-        void setNetworkValid() {
+        void setNetworkValid(boolean isStrictMode) {
             mNmValidationResult = VALIDATION_RESULT_VALID;
             mNmValidationRedirectUrl = null;
+            int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
+            if (isStrictMode) {
+                probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+            }
+            // The probesCompleted equals to probesSucceeded for the case of valid network, so put
+            // the same value into two different parameter of the method.
+            setProbesStatus(probesSucceeded, probesSucceeded);
         }
 
-        void setNetworkInvalid() {
+        void setNetworkInvalid(boolean isStrictMode) {
             mNmValidationResult = VALIDATION_RESULT_INVALID;
             mNmValidationRedirectUrl = null;
+            int probesCompleted = VALIDATION_RESULT_BASE;
+            int probesSucceeded = VALIDATION_RESULT_INVALID;
+            // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
+            // tried to validate the private DNS but failed.
+            if (isStrictMode) {
+                probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
+                probesSucceeded = probesCompleted;
+                probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+            }
+            setProbesStatus(probesCompleted, probesSucceeded);
         }
 
-        void setNetworkPortal(String redirectUrl) {
-            setNetworkInvalid();
+        void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
+            setNetworkInvalid(isStrictMode);
             mNmValidationRedirectUrl = redirectUrl;
+            // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
+            // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
+            int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
+            int probesSucceeded = VALIDATION_RESULT_INVALID;
+            if (isStrictMode) {
+                probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+            }
+            setProbesStatus(probesCompleted, probesSucceeded);
         }
 
         void setNetworkPartial() {
             mNmValidationResult = VALIDATION_RESULT_PARTIAL;
             mNmValidationRedirectUrl = null;
+            int probesCompleted = VALIDATION_RESULT_BASE;
+            int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
+            setProbesStatus(probesCompleted, probesSucceeded);
         }
 
-        void setNetworkPartialValid() {
-            mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
-            mNmValidationRedirectUrl = null;
+        void setNetworkPartialValid(boolean isStrictMode) {
+            setNetworkPartial();
+            mNmValidationResult |= VALIDATION_RESULT_VALID;
+            int probesCompleted = VALIDATION_RESULT_BASE;
+            int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
+            // Suppose the partial network cannot pass the private DNS validation as well, so only
+            // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
+            if (isStrictMode) {
+                probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+            }
+            setProbesStatus(probesCompleted, probesSucceeded);
+        }
+
+        void setProbesStatus(int probesCompleted, int probesSucceeded) {
+            mProbesCompleted = probesCompleted;
+            mProbesSucceeded = probesSucceeded;
         }
 
         public String waitForRedirectUrl() {
@@ -2226,7 +2271,7 @@
 
         // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
         // probe.
-        mWiFiNetworkAgent.setNetworkPartialValid();
+        mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
         // If the user chooses yes to use this partial connectivity wifi, switch the default
         // network to wifi and check if wifi becomes valid or not.
         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
@@ -2299,7 +2344,7 @@
         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
-        mWiFiNetworkAgent.setNetworkValid();
+        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
 
         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
         // validated.
@@ -2317,7 +2362,7 @@
         // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
         // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
         // notifyNetworkConnected.
-        mWiFiNetworkAgent.connectWithPartialValidConnectivity();
+        mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
@@ -2343,7 +2388,7 @@
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String redirectUrl = "http://android.com/path";
-        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
+        mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
 
@@ -2361,7 +2406,7 @@
                 mWiFiNetworkAgent);
 
         // Report partial connectivity is accepted.
-        mWiFiNetworkAgent.setNetworkPartialValid();
+        mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
         mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
                 false /* always */);
         waitForIdle();
@@ -2392,7 +2437,7 @@
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String firstRedirectUrl = "http://example.com/firstPath";
-        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
+        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
 
@@ -2405,13 +2450,13 @@
         // Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String secondRedirectUrl = "http://example.com/secondPath";
-        mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
+        mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
 
         // Make captive portal disappear then revalidate.
         // Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
-        mWiFiNetworkAgent.setNetworkValid();
+        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
 
@@ -2423,7 +2468,7 @@
 
         // Break network connectivity.
         // Expect NET_CAPABILITY_VALIDATED onLost callback.
-        mWiFiNetworkAgent.setNetworkInvalid();
+        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
         validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
     }
@@ -2454,7 +2499,7 @@
         mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
 
         // Turn into a captive portal.
-        mWiFiNetworkAgent.setNetworkPortal("http://example.com");
+        mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -2475,7 +2520,7 @@
         assertEquals(testValue, signInIntent.getStringExtra(testKey));
 
         // Report that the captive portal is dismissed, and check that callbacks are fired
-        mWiFiNetworkAgent.setNetworkValid();
+        mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
         mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
         captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -2504,7 +2549,7 @@
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         String firstRedirectUrl = "http://example.com/firstPath";
 
-        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
+        mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
         mWiFiNetworkAgent.expectDisconnected();
         mWiFiNetworkAgent.expectPreventReconnectReceived();
 
@@ -3219,7 +3264,7 @@
         Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
 
         // Fail validation on wifi.
-        mWiFiNetworkAgent.setNetworkInvalid();
+        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -3263,7 +3308,7 @@
         wifiNetwork = mWiFiNetworkAgent.getNetwork();
 
         // Fail validation on wifi and expect the dialog to appear.
-        mWiFiNetworkAgent.setNetworkInvalid();
+        mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
         mCm.reportNetworkConnectivity(wifiNetwork, false);
         defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -4299,7 +4344,7 @@
         mCm.registerNetworkCallback(request, callback);
 
         // Bring up wifi aware network.
-        wifiAware.connect(false, false);
+        wifiAware.connect(false, false, false /* isStrictMode */);
         callback.expectAvailableCallbacksUnvalidated(wifiAware);
 
         assertNull(mCm.getActiveNetworkInfo());
@@ -4537,6 +4582,44 @@
     }
 
     @Test
+    public void testPrivateDnsNotification() throws Exception {
+        NetworkRequest request = new NetworkRequest.Builder()
+                .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
+                .build();
+        TestNetworkCallback callback = new TestNetworkCallback();
+        mCm.registerNetworkCallback(request, callback);
+        // Bring up wifi.
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        // Private DNS resolution failed, checking if the notification will be shown or not.
+        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+        mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+        waitForIdle();
+        // If network validation failed, NetworkMonitor will re-evaluate the network.
+        // ConnectivityService should filter the redundant notification. This part is trying to
+        // simulate that situation and check if ConnectivityService could filter that case.
+        mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+        waitForIdle();
+        verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
+                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+        // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
+        // shown.
+        mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
+        mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+        waitForIdle();
+        verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
+                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
+        // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
+        // shown again.
+        mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+        mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+        waitForIdle();
+        verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
+                eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+    }
+
+    @Test
     public void testPrivateDnsSettingsChange() throws Exception {
         // Clear any interactions that occur as a result of CS starting up.
         reset(mMockDnsResolver);
@@ -4793,7 +4876,7 @@
         // by NetworkMonitor
         assertFalse(NetworkMonitorUtils.isValidationRequired(
                 vpnNetworkAgent.getNetworkCapabilities()));
-        vpnNetworkAgent.setNetworkValid();
+        vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
 
         vpnNetworkAgent.connect(false);
         mMockVpn.connect();
@@ -4882,7 +4965,8 @@
         ranges.add(new UidRange(uid, uid));
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.setUids(ranges);
-        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+                false /* isStrictMode */);
         mMockVpn.connect();
 
         defaultCallback.assertNoCallback();
@@ -4913,7 +4997,8 @@
         ranges.add(new UidRange(uid, uid));
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.setUids(ranges);
-        vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
+        vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
+                false /* isStrictMode */);
         mMockVpn.connect();
 
         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
@@ -4945,7 +5030,8 @@
         ranges.add(new UidRange(uid, uid));
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.setUids(ranges);
-        vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
+        vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
+                false /* isStrictMode */);
         mMockVpn.connect();
 
         // Even though the VPN is unvalidated, it becomes the default network for our app.
@@ -4968,7 +5054,7 @@
                 vpnNetworkAgent.getNetworkCapabilities()));
 
         // Pretend that the VPN network validates.
-        vpnNetworkAgent.setNetworkValid();
+        vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
         vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
         // Expect to see the validated capability, but no other changes, because the VPN is already
         // the default network for the app.
@@ -5000,7 +5086,8 @@
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.connect();
         mMockVpn.setUids(ranges);
-        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+                false /* isStrictMode */);
 
         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
@@ -5099,7 +5186,8 @@
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.connect();
         mMockVpn.setUids(ranges);
-        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+                false /* isStrictMode */);
 
         vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
         nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index c030c3e..5f62c08 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -25,8 +25,10 @@
 import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
 import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
 import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
@@ -90,6 +92,9 @@
 import android.net.util.SharedLog;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pInfo;
+import android.net.wifi.p2p.WifiP2pManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.INetworkManagementService;
@@ -140,6 +145,7 @@
     private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
     private static final String TEST_USB_IFNAME = "test_rndis0";
     private static final String TEST_WLAN_IFNAME = "test_wlan0";
+    private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
 
     private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
 
@@ -216,9 +222,10 @@
             assertTrue("Non-mocked interface " + ifName,
                     ifName.equals(TEST_USB_IFNAME)
                             || ifName.equals(TEST_WLAN_IFNAME)
-                            || ifName.equals(TEST_MOBILE_IFNAME));
+                            || ifName.equals(TEST_MOBILE_IFNAME)
+                            || ifName.equals(TEST_P2P_IFNAME));
             final String[] ifaces = new String[] {
-                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
+                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME};
             return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
                     MacAddress.ALL_ZEROS_ADDRESS);
         }
@@ -361,6 +368,8 @@
                 .thenReturn(new String[] { "test_rndis\\d" });
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
                 .thenReturn(new String[]{ "test_wlan\\d" });
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
+                .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
                 .thenReturn(new String[0]);
         when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
@@ -369,7 +378,7 @@
                 .thenReturn(false);
         when(mNMService.listInterfaces())
                 .thenReturn(new String[] {
-                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
+                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
         when(mNMService.getInterfaceConfig(anyString()))
                 .thenReturn(new InterfaceConfiguration());
         when(mRouterAdvertisementDaemon.start())
@@ -423,6 +432,31 @@
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private static final String[] P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST = {
+            android.Manifest.permission.ACCESS_FINE_LOCATION,
+            android.Manifest.permission.ACCESS_WIFI_STATE
+    };
+
+    private void sendWifiP2pConnectionChanged(
+            boolean isGroupFormed, boolean isGroupOwner, String ifname) {
+        WifiP2pInfo p2pInfo = new WifiP2pInfo();
+        p2pInfo.groupFormed = isGroupFormed;
+        p2pInfo.isGroupOwner = isGroupOwner;
+
+        NetworkInfo networkInfo = new NetworkInfo(TYPE_WIFI_P2P, 0, null, null);
+
+        WifiP2pGroup group = new WifiP2pGroup();
+        group.setIsGroupOwner(isGroupOwner);
+        group.setInterface(ifname);
+
+        final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
+        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, p2pInfo);
+        intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, networkInfo);
+        intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, group);
+        mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
+                P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
+    }
+
     private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
         final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
         intent.putExtra(USB_CONNECTED, connected);
@@ -436,11 +470,11 @@
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
-    private void verifyInterfaceServingModeStarted() throws Exception {
-        verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
+    private void verifyInterfaceServingModeStarted(String ifname) throws Exception {
+        verify(mNMService, times(1)).getInterfaceConfig(ifname);
         verify(mNMService, times(1))
-                .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
-        verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
+                .setInterfaceConfig(eq(ifname), any(InterfaceConfiguration.class));
+        verify(mNMService, times(1)).tetherInterface(ifname);
     }
 
     private void verifyTetheringBroadcast(String ifname, String whichExtra) {
@@ -530,7 +564,7 @@
         sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
         mLooper.dispatchAll();
 
-        verifyInterfaceServingModeStarted();
+        verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
@@ -542,8 +576,9 @@
         verifyNoMoreInteractions(mWifiManager);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
         verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
-        // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
-        assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
+        // This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
+        // and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
+        assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
 
         // Emulate externally-visible WifiManager effects, when hotspot mode
         // is being torn down.
@@ -552,9 +587,9 @@
         mLooper.dispatchAll();
 
         verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
-        // TODO: Why is {g,s}etInterfaceConfig() called more than once?
-        verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
-        verify(mNMService, atLeastOnce())
+        // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
+        verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
+        verify(mNMService, times(2))
                 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
         verify(mNMService, times(1)).stopTethering();
         verify(mNMService, times(1)).setIpForwardingEnabled(false);
@@ -770,7 +805,7 @@
         sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
         mLooper.dispatchAll();
 
-        verifyInterfaceServingModeStarted();
+        verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
@@ -785,8 +820,9 @@
         // In tethering mode, in the default configuration, an explicit request
         // for a mobile network is also made.
         verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
-        // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
-        assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
+        // This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
+        // and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
+        assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
 
         /////
         // We do not currently emulate any upstream being found.
@@ -809,7 +845,7 @@
         mLooper.dispatchAll();
 
         verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
-        // TODO: Why is {g,s}etInterfaceConfig() called more than once?
+        // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
         verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
         verify(mNMService, atLeastOnce())
                 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
@@ -857,8 +893,9 @@
                 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
         verify(mWifiManager).updateInterfaceIpState(
                 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
-        // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
-        assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
+        // There are 3 state change event:
+        // AVAILABLE -> STATE_TETHERED -> STATE_AVAILABLE.
+        assertEquals(3, mTetheringDependencies.isTetheringSupportedCalls);
         verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
         // This is called, but will throw.
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
@@ -1031,6 +1068,133 @@
         assertEquals(fakeSubId, newConfig.subId);
     }
 
+    private void workingWifiP2pGroupOwner(
+            boolean emulateInterfaceStatusChanged) throws Exception {
+        if (emulateInterfaceStatusChanged) {
+            mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
+        }
+        sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
+        verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
+        verify(mNMService, times(1)).setIpForwardingEnabled(true);
+        verify(mNMService, times(1)).startTethering(any(String[].class));
+        verifyNoMoreInteractions(mNMService);
+        verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
+        verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
+        // This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
+        // and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
+        assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
+
+        assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+
+        // Emulate externally-visible WifiP2pManager effects, when wifi p2p group
+        // is being removed.
+        sendWifiP2pConnectionChanged(false, true, TEST_P2P_IFNAME);
+        mTethering.interfaceRemoved(TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, times(1)).untetherInterface(TEST_P2P_IFNAME);
+        // {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
+        verify(mNMService, times(2)).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, times(2))
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, times(1)).stopTethering();
+        verify(mNMService, times(1)).setIpForwardingEnabled(false);
+        verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream();
+        verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
+        verifyNoMoreInteractions(mNMService);
+        // Asking for the last error after the per-interface state machine
+        // has been reaped yields an unknown interface error.
+        assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+    }
+
+    private void workingWifiP2pGroupClient(
+            boolean emulateInterfaceStatusChanged) throws Exception {
+        if (emulateInterfaceStatusChanged) {
+            mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
+        }
+        sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, never())
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
+        verify(mNMService, never()).setIpForwardingEnabled(true);
+        verify(mNMService, never()).startTethering(any(String[].class));
+
+        // Emulate externally-visible WifiP2pManager effects, when wifi p2p group
+        // is being removed.
+        sendWifiP2pConnectionChanged(false, false, TEST_P2P_IFNAME);
+        mTethering.interfaceRemoved(TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, never()).untetherInterface(TEST_P2P_IFNAME);
+        verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, never())
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, never()).stopTethering();
+        verify(mNMService, never()).setIpForwardingEnabled(false);
+        verifyNoMoreInteractions(mNMService);
+        // Asking for the last error after the per-interface state machine
+        // has been reaped yields an unknown interface error.
+        assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+    }
+
+    @Test
+    public void workingWifiP2pGroupOwnerWithIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwner(true);
+    }
+
+    @Test
+    public void workingWifiP2pGroupOwnerSansIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwner(false);
+    }
+
+    private void workingWifiP2pGroupOwnerLegacyMode(
+            boolean emulateInterfaceStatusChanged) throws Exception {
+        // change to legacy mode and update tethering information by chaning SIM
+        when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
+                .thenReturn(new String[]{});
+        final int fakeSubId = 1234;
+        mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
+
+        if (emulateInterfaceStatusChanged) {
+            mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
+        }
+        sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
+        mLooper.dispatchAll();
+
+        verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
+        verify(mNMService, never())
+                .setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
+        verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
+        verify(mNMService, never()).setIpForwardingEnabled(true);
+        verify(mNMService, never()).startTethering(any(String[].class));
+        assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
+    }
+    @Test
+    public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwnerLegacyMode(true);
+    }
+
+    @Test
+    public void workingWifiP2pGroupOwnerLegacyModeSansIfaceChanged() throws Exception {
+        workingWifiP2pGroupOwnerLegacyMode(false);
+    }
+
+    @Test
+    public void workingWifiP2pGroupClientWithIfaceChanged() throws Exception {
+        workingWifiP2pGroupClient(true);
+    }
+
+    @Test
+    public void workingWifiP2pGroupClientSansIfaceChanged() throws Exception {
+        workingWifiP2pGroupClient(false);
+    }
+
     // TODO: Test that a request for hotspot mode doesn't interfere with an
     // already operating tethering mode interface.
 }
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index c9e3404..957216e 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -41,6 +41,7 @@
             "android.view.DisplayCutoutTest",
             "android.view.InsetsAnimationControlImplTest",
             "android.view.InsetsControllerTest",
+            "android.view.InsetsFlagsTest",
             "android.view.InsetsSourceTest",
             "android.view.InsetsSourceConsumerTest",
             "android.view.InsetsStateTest",
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 05375b0..21386b8 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -787,7 +787,9 @@
 
     // The dynamicRefTable can be null if there are no resources for this asset cookie.
     // This fine.
-    const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
+    auto noop_destructor = [](const DynamicRefTable* /*ref_table */) { };
+    auto dynamicRefTable = std::shared_ptr<const DynamicRefTable>(
+        res.getDynamicRefTableForCookie(assetsCookie), noop_destructor);
 
     Asset* asset = NULL;
 
diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp
index f189048..9cef7b3 100644
--- a/tools/aapt2/format/Container.cpp
+++ b/tools/aapt2/format/Container.cpp
@@ -30,6 +30,7 @@
 
 constexpr const static uint32_t kContainerFormatMagic = 0x54504141u;
 constexpr const static uint32_t kContainerFormatVersion = 1u;
+constexpr const static size_t kPaddingAlignment = 4u;
 
 ContainerWriter::ContainerWriter(ZeroCopyOutputStream* out, size_t entry_count)
     : out_(out), total_entry_count_(entry_count), current_entry_count_(0u) {
@@ -49,11 +50,17 @@
   }
 }
 
-inline static void WritePadding(int padding, CodedOutputStream* out) {
-  if (padding < 4) {
-    const uint32_t zero = 0u;
-    out->WriteRaw(&zero, padding);
-  }
+inline static size_t CalculatePaddingForAlignment(size_t size) {
+  size_t overage = size % kPaddingAlignment;
+  return overage == 0 ? 0 : kPaddingAlignment - overage;
+}
+
+inline static void WritePadding(size_t padding, CodedOutputStream* out) {
+  CHECK(padding < kPaddingAlignment);
+  const uint32_t zero = 0u;
+  static_assert(sizeof(zero) >= kPaddingAlignment, "Not enough source bytes for padding");
+
+  out->WriteRaw(&zero, padding);
 }
 
 bool ContainerWriter::AddResTableEntry(const pb::ResourceTable& table) {
@@ -70,7 +77,7 @@
 
   // Write the aligned size.
   const ::google::protobuf::uint64 size = table.ByteSize();
-  const int padding = 4 - (size % 4);
+  const int padding = CalculatePaddingForAlignment(size);
   coded_out.WriteLittleEndian64(size);
 
   // Write the table.
@@ -103,9 +110,9 @@
 
   // Write the aligned size.
   const ::google::protobuf::uint32 header_size = file.ByteSize();
-  const int header_padding = 4 - (header_size % 4);
+  const int header_padding = CalculatePaddingForAlignment(header_size);
   const ::google::protobuf::uint64 data_size = in->TotalSize();
-  const int data_padding = 4 - (data_size % 4);
+  const int data_padding = CalculatePaddingForAlignment(data_size);
   coded_out.WriteLittleEndian64(kResFileEntryHeaderSize + header_size + header_padding + data_size +
                                 data_padding);
 
diff --git a/tools/aapt2/format/binary/XmlFlattener_test.cpp b/tools/aapt2/format/binary/XmlFlattener_test.cpp
index 1dac493..c24488b 100644
--- a/tools/aapt2/format/binary/XmlFlattener_test.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener_test.cpp
@@ -226,10 +226,10 @@
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
   // The tree needs a custom DynamicRefTable since it is not using a standard app ID (0x7f).
-  android::DynamicRefTable dynamic_ref_table;
-  dynamic_ref_table.addMapping(0x80, 0x80);
+  auto dynamic_ref_table = std::make_shared<android::DynamicRefTable>();
+  dynamic_ref_table->addMapping(0x80, 0x80);
 
-  android::ResXMLTree tree(&dynamic_ref_table);
+  auto tree = android::ResXMLTree(std::move(dynamic_ref_table));
   ASSERT_TRUE(Flatten(doc.get(), &tree));
 
   while (tree.next() != android::ResXMLTree::START_TAG) {
diff --git a/tools/aapt2/formats.md b/tools/aapt2/formats.md
index bb31a00..25a0e79 100644
--- a/tools/aapt2/formats.md
+++ b/tools/aapt2/formats.md
@@ -23,7 +23,7 @@
 | Size (in bytes) | Field          | Description                                                                                               |
 |:----------------|:---------------|:----------------------------------------------------------------------------------------------------------|
 | `4`             | `entry_type`   | The type of the entry. This can be one of two types: `RES_TABLE (0x00000000)` or `RES_FILE (0x00000001)`. |
-| `8`             | `entry_length` | The length of the data that follows.                                                                      |
+| `8`             | `entry_length` | The length of the data that follows.  Do not use if `entry_type` is `RES_FILE`; this value may be wrong.  |
 | `entry_length`  | `data`         | The payload. The contents of this varies based on the `entry_type`.                                       |
 
 If the `entry_type` is equal to `RES_TABLE (0x00000000)`, the `data` field contains a serialized
@@ -32,13 +32,14 @@
 If the `entry_type` is equal to `RES_FILE (0x00000001)`, the `data` field contains the following:
 
 
-| Size (in bytes) | Field          | Description                                                                                               |
-|:----------------|:---------------|:----------------------------------------------------------------------------------------------------------|
-| `4`             | `header_size`  | The size of the `header` field.                                                                 |
-| `8`             | `data_size`    | The size of the `data` field.                                                                   |
-| `header_size`   | `header`       | The serialized Protobuf message [aapt.pb.internal.CompiledFile](ResourcesInternal.proto).       |
-| `x`             | `padding`      | Up to 4 bytes of zeros, if padding is necessary to align the `data` field on a 32-bit boundary. |
-| `data_size`     | `data`         | The payload, which is determined by the `type` field in the `aapt.pb.internal.CompiledFile`. This can be a PNG file, binary XML, or [aapt.pb.XmlNode](Resources.proto). |
+| Size (in bytes) | Field            | Description                                                                                               |
+|:----------------|:-----------------|:----------------------------------------------------------------------------------------------------------|
+| `4`             | `header_size`    | The size of the `header` field.                                                                           |
+| `8`             | `data_size`      | The size of the `data` field.                                                                             |
+| `header_size`   | `header`         | The serialized Protobuf message [aapt.pb.internal.CompiledFile](ResourcesInternal.proto).                 |
+| `x`             | `header_padding` | Up to 3 bytes of zeros, if padding is necessary to align the `data` field on a 32-bit boundary.           |
+| `data_size`     | `data`           | The payload, which is determined by the `type` field in the `aapt.pb.internal.CompiledFile`. This can be a PNG file, binary XML, or [aapt.pb.XmlNode](Resources.proto). |
+| `y`             | `data_padding`   | Up to 3 bytes of zeros, if `data_size` is not a multiple of 4.                                            |
 
 ## AAPT2 Static Library Format (extension `.sapk`)
 
diff --git a/tools/bit/main.cpp b/tools/bit/main.cpp
index d80c2e7..fd184f5 100644
--- a/tools/bit/main.cpp
+++ b/tools/bit/main.cpp
@@ -708,10 +708,12 @@
         }
     }
 
+
     // Figure out whether we need to sync the system and which apks to install
     string deviceTargetPath = buildOut + "/target/product/" + buildDevice;
     string systemPath = deviceTargetPath + "/system/";
     string dataPath = deviceTargetPath + "/data/";
+    string testPath = deviceTargetPath + "/testcases/";
     bool syncSystem = false;
     bool alwaysSyncSystem = false;
     vector<string> systemFiles;
@@ -734,7 +736,8 @@
                     continue;
                 }
                 // Apk in the data partition
-                if (starts_with(file, dataPath) && ends_with(file, ".apk")) {
+                if (ends_with(file, ".apk")
+                        && (starts_with(file, dataPath) || starts_with(file, testPath))) {
                     // Always install it if we didn't build it because otherwise
                     // it will never have changed.
                     installApks.push_back(InstallApk(file, !target->build));
@@ -966,8 +969,9 @@
             for (size_t j=0; j<target->module.installed.size(); j++) {
                 string filename = target->module.installed[j];
 
-                // Apk in the data partition
-                if (!starts_with(filename, dataPath) || !ends_with(filename, ".apk")) {
+                // Skip of not apk in the data partition or test
+                if (!(ends_with(filename, ".apk")
+                        && (starts_with(filename, dataPath) || starts_with(filename, testPath)))) {
                     continue;
                 }
 
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index 0ebb3cf..431f378 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -417,7 +417,7 @@
     if (!isMethodGenerationSuppressed("writeToParcel", Parcel, "int")) {
         +"@Override"
         +GENERATED_MEMBER_HEADER
-        "public void writeToParcel($Parcel dest, int flags)" {
+        "public void writeToParcel(@$NonNull $Parcel dest, int flags)" {
             +"// You can override field parcelling by defining methods like:"
             +"// void parcelFieldName(Parcel dest, int flags) { ... }"
             +""
@@ -473,7 +473,7 @@
         +"/** @hide */"
         +"@SuppressWarnings({\"unchecked\", \"RedundantCast\"})"
         +GENERATED_MEMBER_HEADER
-        "$visibility $ClassName($Parcel in) {" {
+        "$visibility $ClassName(@$NonNull $Parcel in) {" {
             +"// You can override field unparcelling by defining methods like:"
             +"// static FieldType unparcelFieldName(Parcel in) { ... }"
             +""
@@ -598,7 +598,7 @@
             }
 
             +"@Override"
-            "public $ClassName createFromParcel($Parcel in)" {
+            "public $ClassName createFromParcel(@$NonNull $Parcel in)" {
                 +"return new $ClassName(in);"
             }
             rmEmptyLine()
@@ -611,7 +611,7 @@
     if (!isMethodGenerationSuppressed("equals", "Object")) {
         +"@Override"
         +GENERATED_MEMBER_HEADER
-        "public boolean equals(Object o)" {
+        "public boolean equals(@$Nullable Object o)" {
             +"// You can override field equality logic by defining either of the methods like:"
             +"// boolean fieldNameEquals($ClassName other) { ... }"
             +"// boolean fieldNameEquals(FieldType otherValue) { ... }"
@@ -904,7 +904,7 @@
         usedSpecializationsSet.toList().forEachLastAware { specType, isLast ->
             val SpecType = specType.capitalize()
             val ActionClass = classRef("com.android.internal.util.DataClass.Per${SpecType}FieldAction")
-            +"$ActionClass<$ClassType> action$SpecType${if_(!isLast, ",")}"
+            +"@$NonNull $ActionClass<$ClassType> action$SpecType${if_(!isLast, ",")}"
         }
     }; " {" {
         usedSpecializations.forEachIndexed { i, specType ->
@@ -919,7 +919,7 @@
         +"/** @deprecated May cause boxing allocations - use with caution! */"
         +"@Deprecated"
         +GENERATED_MEMBER_HEADER
-        "void forEachField($PerObjectFieldAction<$ClassType> action)" {
+        "void forEachField(@$NonNull $PerObjectFieldAction<$ClassType> action)" {
             fields.forEachApply {
                 +"action.acceptObject(this, \"$nameLowerCamel\", $name);"
             }
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 8c4583f..3eb9e7b 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.8"
+const val CODEGEN_VERSION = "1.0.9"
 
 const val CANONICAL_BUILDER_CLASS = "Builder"
 const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt b/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt
index 3dfa4d2..bfbbf7a 100644
--- a/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/CommandOptions.kt
@@ -27,19 +27,21 @@
 
         private const val PROTOLOG_CLASS_PARAM = "--protolog-class"
         private const val PROTOLOGIMPL_CLASS_PARAM = "--protolog-impl-class"
+        private const val PROTOLOGCACHE_CLASS_PARAM = "--protolog-cache-class"
         private const val PROTOLOGGROUP_CLASS_PARAM = "--loggroups-class"
         private const val PROTOLOGGROUP_JAR_PARAM = "--loggroups-jar"
         private const val VIEWER_CONFIG_JSON_PARAM = "--viewer-conf"
         private const val OUTPUT_SOURCE_JAR_PARAM = "--output-srcjar"
         private val parameters = setOf(PROTOLOG_CLASS_PARAM, PROTOLOGIMPL_CLASS_PARAM,
-                PROTOLOGGROUP_CLASS_PARAM, PROTOLOGGROUP_JAR_PARAM, VIEWER_CONFIG_JSON_PARAM,
-                OUTPUT_SOURCE_JAR_PARAM)
+                PROTOLOGCACHE_CLASS_PARAM, PROTOLOGGROUP_CLASS_PARAM, PROTOLOGGROUP_JAR_PARAM,
+                VIEWER_CONFIG_JSON_PARAM, OUTPUT_SOURCE_JAR_PARAM)
 
         val USAGE = """
             Usage: ${Constants.NAME} <command> [<args>]
             Available commands:
 
             $TRANSFORM_CALLS_CMD $PROTOLOG_CLASS_PARAM <class name> $PROTOLOGIMPL_CLASS_PARAM
+                <class name> $PROTOLOGCACHE_CLASS_PARAM
                 <class name> $PROTOLOGGROUP_CLASS_PARAM <class name> $PROTOLOGGROUP_JAR_PARAM
                 <config.jar> $OUTPUT_SOURCE_JAR_PARAM <output.srcjar> [<input.java>]
             - processes java files replacing stub calls with logging code.
@@ -54,7 +56,7 @@
         """.trimIndent()
 
         private fun validateClassName(name: String): String {
-            if (!Pattern.matches("^([a-z]+[A-Za-z0-9]*\\.)+([A-Za-z0-9]+)$", name)) {
+            if (!Pattern.matches("^([a-z]+[A-Za-z0-9]*\\.)+([A-Za-z0-9$]+)$", name)) {
                 throw InvalidCommandException("Invalid class name $name")
             }
             return name
@@ -121,6 +123,7 @@
     val protoLogClassNameArg: String
     val protoLogGroupsClassNameArg: String
     val protoLogImplClassNameArg: String
+    val protoLogCacheClassNameArg: String
     val protoLogGroupsJarArg: String
     val viewerConfigJsonArg: String
     val outputSourceJarArg: String
@@ -170,6 +173,8 @@
                         params))
                 protoLogImplClassNameArg = validateClassName(getParam(PROTOLOGIMPL_CLASS_PARAM,
                         params))
+                protoLogCacheClassNameArg = validateClassName(getParam(PROTOLOGCACHE_CLASS_PARAM,
+                        params))
                 protoLogGroupsJarArg = validateJarName(getParam(PROTOLOGGROUP_JAR_PARAM, params))
                 viewerConfigJsonArg = validateNotSpecified(VIEWER_CONFIG_JSON_PARAM, params)
                 outputSourceJarArg = validateSrcJarName(getParam(OUTPUT_SOURCE_JAR_PARAM, params))
@@ -181,6 +186,7 @@
                 protoLogGroupsClassNameArg = validateClassName(getParam(PROTOLOGGROUP_CLASS_PARAM,
                         params))
                 protoLogImplClassNameArg = validateNotSpecified(PROTOLOGIMPL_CLASS_PARAM, params)
+                protoLogCacheClassNameArg = validateNotSpecified(PROTOLOGCACHE_CLASS_PARAM, params)
                 protoLogGroupsJarArg = validateJarName(getParam(PROTOLOGGROUP_JAR_PARAM, params))
                 viewerConfigJsonArg = validateJSONName(getParam(VIEWER_CONFIG_JSON_PARAM, params))
                 outputSourceJarArg = validateNotSpecified(OUTPUT_SOURCE_JAR_PARAM, params)
@@ -191,6 +197,7 @@
                 protoLogClassNameArg = validateNotSpecified(PROTOLOG_CLASS_PARAM, params)
                 protoLogGroupsClassNameArg = validateNotSpecified(PROTOLOGGROUP_CLASS_PARAM, params)
                 protoLogImplClassNameArg = validateNotSpecified(PROTOLOGIMPL_CLASS_PARAM, params)
+                protoLogCacheClassNameArg = validateNotSpecified(PROTOLOGCACHE_CLASS_PARAM, params)
                 protoLogGroupsJarArg = validateNotSpecified(PROTOLOGGROUP_JAR_PARAM, params)
                 viewerConfigJsonArg = validateJSONName(getParam(VIEWER_CONFIG_JSON_PARAM, params))
                 outputSourceJarArg = validateNotSpecified(OUTPUT_SOURCE_JAR_PARAM, params)
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index 70ac0be..629f720 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -18,11 +18,14 @@
 
 import com.android.protolog.tool.CommandOptions.Companion.USAGE
 import com.github.javaparser.ParseProblemException
+import com.github.javaparser.ParserConfiguration
 import com.github.javaparser.StaticJavaParser
 import com.github.javaparser.ast.CompilationUnit
 import java.io.File
 import java.io.FileInputStream
 import java.io.FileOutputStream
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
 import java.util.jar.JarOutputStream
 import java.util.zip.ZipEntry
 import kotlin.system.exitProcess
@@ -45,34 +48,86 @@
         val outJar = JarOutputStream(out)
         val processor = ProtoLogCallProcessor(command.protoLogClassNameArg,
                 command.protoLogGroupsClassNameArg, groups)
-        val transformer = SourceTransformer(command.protoLogImplClassNameArg, processor)
 
-        command.javaSourceArgs.forEach { path ->
-            val file = File(path)
-            val text = file.readText()
-            val newPath = path
-            val outSrc = try {
-                val code = tryParse(text, path)
-                if (containsProtoLogText(text, command.protoLogClassNameArg)) {
-                    transformer.processClass(text, newPath, code)
-                } else {
+        val executor = newThreadPool()
+
+        command.javaSourceArgs.map { path ->
+            executor.submitCallable {
+                val transformer = SourceTransformer(command.protoLogImplClassNameArg,
+                        command.protoLogCacheClassNameArg, processor)
+                val file = File(path)
+                val text = file.readText()
+                val outSrc = try {
+                    val code = tryParse(text, path)
+                    if (containsProtoLogText(text, command.protoLogClassNameArg)) {
+                        transformer.processClass(text, path, code)
+                    } else {
+                        text
+                    }
+                } catch (ex: ParsingException) {
+                    // If we cannot parse this file, skip it (and log why). Compilation will fail
+                    // in a subsequent build step.
+                    println("\n${ex.message}\n")
                     text
                 }
-            } catch (ex: ParsingException) {
-                // If we cannot parse this file, skip it (and log why). Compilation will fail
-                // in a subsequent build step.
-                println("\n${ex.message}\n")
-                text
+                path to outSrc
             }
-            outJar.putNextEntry(ZipEntry(newPath))
+        }.map { future ->
+            val (path, outSrc) = future.get()
+            outJar.putNextEntry(ZipEntry(path))
             outJar.write(outSrc.toByteArray())
             outJar.closeEntry()
         }
 
+        executor.shutdown()
+
+        val cacheSplit = command.protoLogCacheClassNameArg.split(".")
+        val cacheName = cacheSplit.last()
+        val cachePackage = cacheSplit.dropLast(1).joinToString(".")
+        val cachePath = "gen/${cacheSplit.joinToString("/")}.java"
+
+        outJar.putNextEntry(ZipEntry(cachePath))
+        outJar.write(generateLogGroupCache(cachePackage, cacheName, groups,
+                command.protoLogImplClassNameArg, command.protoLogGroupsClassNameArg).toByteArray())
+
         outJar.close()
         out.close()
     }
 
+    fun generateLogGroupCache(
+        cachePackage: String,
+        cacheName: String,
+        groups: Map<String, LogGroup>,
+        protoLogImplClassName: String,
+        protoLogGroupsClassName: String
+    ): String {
+        val fields = groups.values.map {
+            "public static boolean ${it.name}_enabled = false;"
+        }.joinToString("\n")
+
+        val updates = groups.values.map {
+            "${it.name}_enabled = " +
+                    "$protoLogImplClassName.isEnabled($protoLogGroupsClassName.${it.name});"
+        }.joinToString("\n")
+
+        return """
+            package $cachePackage;
+
+            public class $cacheName {
+${fields.replaceIndent("                ")}
+
+                static {
+                    $protoLogImplClassName.sCacheUpdater = $cacheName::update;
+                    update();
+                }
+
+                static void update() {
+${updates.replaceIndent("                    ")}
+                }
+            }
+        """.trimIndent()
+    }
+
     private fun tryParse(code: String, fileName: String): CompilationUnit {
         try {
             return StaticJavaParser.parse(code)
@@ -92,23 +147,36 @@
         val processor = ProtoLogCallProcessor(command.protoLogClassNameArg,
                 command.protoLogGroupsClassNameArg, groups)
         val builder = ViewerConfigBuilder(processor)
-        command.javaSourceArgs.forEach { path ->
-            val file = File(path)
-            val text = file.readText()
-            if (containsProtoLogText(text, command.protoLogClassNameArg)) {
-                try {
-                    val code = tryParse(text, path)
-                    val pack = if (code.packageDeclaration.isPresent) code.packageDeclaration
-                            .get().nameAsString else ""
-                    val newPath = pack.replace('.', '/') + '/' + file.name
-                    builder.processClass(code, newPath)
-                } catch (ex: ParsingException) {
-                    // If we cannot parse this file, skip it (and log why). Compilation will fail
-                    // in a subsequent build step.
-                    println("\n${ex.message}\n")
+
+        val executor = newThreadPool()
+
+        command.javaSourceArgs.map { path ->
+            executor.submitCallable {
+                val file = File(path)
+                val text = file.readText()
+                if (containsProtoLogText(text, command.protoLogClassNameArg)) {
+                    try {
+                        val code = tryParse(text, path)
+                        val pack = if (code.packageDeclaration.isPresent) code.packageDeclaration
+                                .get().nameAsString else ""
+                        val newPath = pack.replace('.', '/') + '/' + file.name
+                        builder.findLogCalls(code, newPath)
+                    } catch (ex: ParsingException) {
+                        // If we cannot parse this file, skip it (and log why). Compilation will fail
+                        // in a subsequent build step.
+                        println("\n${ex.message}\n")
+                        null
+                    }
+                } else {
+                    null
                 }
             }
+        }.forEach { future ->
+            builder.addLogCalls(future.get() ?: return@forEach)
         }
+
+        executor.shutdown()
+
         val out = FileOutputStream(command.viewerConfigJsonArg)
         out.write(builder.build().toByteArray())
         out.close()
@@ -122,6 +190,11 @@
 
     @JvmStatic
     fun main(args: Array<String>) {
+        StaticJavaParser.setConfiguration(ParserConfiguration().apply {
+            setLanguageLevel(ParserConfiguration.LanguageLevel.RAW)
+            setAttributeComments(false)
+        })
+
         try {
             val command = CommandOptions(args)
             when (command.command) {
@@ -138,3 +211,8 @@
         }
     }
 }
+
+private fun <T> ExecutorService.submitCallable(f: () -> T) = submit(f)
+
+private fun newThreadPool() = Executors.newFixedThreadPool(
+        Runtime.getRuntime().availableProcessors())
diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
index 00fd038..0ad8091 100644
--- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
@@ -16,7 +16,6 @@
 
 package com.android.protolog.tool
 
-import com.android.protolog.tool.Constants.IS_ENABLED_METHOD
 import com.android.server.protolog.common.LogDataType
 import com.github.javaparser.StaticJavaParser
 import com.github.javaparser.ast.CompilationUnit
@@ -42,10 +41,10 @@
 import com.github.javaparser.ast.type.Type
 import com.github.javaparser.printer.PrettyPrinter
 import com.github.javaparser.printer.PrettyPrinterConfiguration
-import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter
 
 class SourceTransformer(
     protoLogImplClassName: String,
+    protoLogCacheClassName: String,
     private val protoLogCallProcessor: ProtoLogCallProcessor
 ) : ProtoLogCallVisitor {
     override fun processCall(
@@ -92,10 +91,9 @@
             // Replace call to a stub method with an actual implementation.
             // Out: com.android.server.protolog.ProtoLogImpl.e(GROUP, 1234, null, arg)
             newCall.setScope(protoLogImplClassNode)
-            // Create a call to ProtoLogImpl.isEnabled(GROUP)
-            // Out: com.android.server.protolog.ProtoLogImpl.isEnabled(GROUP)
-            val isLogEnabled = MethodCallExpr(protoLogImplClassNode, IS_ENABLED_METHOD,
-                NodeList<Expression>(newCall.arguments[0].clone()))
+            // Create a call to ProtoLog$Cache.GROUP_enabled
+            // Out: com.android.server.protolog.ProtoLog$Cache.GROUP_enabled
+            val isLogEnabled = FieldAccessExpr(protoLogCacheClassNode, "${group.name}_enabled")
             if (argTypes.size != call.arguments.size - 2) {
                 throw InvalidProtoLogCallException(
                         "Number of arguments (${argTypes.size} does not mach format" +
@@ -135,7 +133,8 @@
         // Inline the new statement.
         val printedIfStmt = inlinePrinter.print(ifStmt)
         // Append blank lines to preserve line numbering in file (to allow debugging)
-        val newLines = LexicalPreservingPrinter.print(parentStmt).count { c -> c == '\n' }
+        val parentRange = parentStmt.range.get()
+        val newLines = parentRange.end.line - parentRange.begin.line
         val newStmt = printedIfStmt.substringBeforeLast('}') + ("\n".repeat(newLines)) + '}'
         // pre-workaround code, see explanation below
         /*
@@ -211,6 +210,8 @@
 
     private val protoLogImplClassNode =
             StaticJavaParser.parseExpression<FieldAccessExpr>(protoLogImplClassName)
+    private val protoLogCacheClassNode =
+            StaticJavaParser.parseExpression<FieldAccessExpr>(protoLogCacheClassName)
     private var processedCode: MutableList<String> = mutableListOf()
     private var offsets: IntArray = IntArray(0)
     private var fileName: String = ""
@@ -224,9 +225,7 @@
         fileName = path
         processedCode = code.split('\n').toMutableList()
         offsets = IntArray(processedCode.size)
-        LexicalPreservingPrinter.setup(compilationUnit)
         protoLogCallProcessor.process(compilationUnit, this, fileName)
-        // return LexicalPreservingPrinter.print(compilationUnit)
         return processedCode.joinToString("\n")
     }
 }
diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
index 941455a..c100826 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
@@ -23,39 +23,52 @@
 import java.io.StringWriter
 
 class ViewerConfigBuilder(
-    private val protoLogCallVisitor: ProtoLogCallProcessor
-) : ProtoLogCallVisitor {
-    override fun processCall(
-        call: MethodCallExpr,
-        messageString: String,
-        level: LogLevel,
-        group: LogGroup
-    ) {
+    private val processor: ProtoLogCallProcessor
+) {
+    private fun addLogCall(logCall: LogCall, context: ParsingContext) {
+        val group = logCall.logGroup
+        val messageString = logCall.messageString
         if (group.enabled) {
-            val position = fileName
-            val key = CodeUtils.hash(position, messageString, level, group)
+            val key = logCall.key()
             if (statements.containsKey(key)) {
-                if (statements[key] != LogCall(messageString, level, group, position)) {
+                if (statements[key] != logCall) {
                     throw HashCollisionException(
                             "Please modify the log message \"$messageString\" " +
-                                    "or \"${statements[key]}\" - their hashes are equal.",
-                            ParsingContext(fileName, call))
+                                    "or \"${statements[key]}\" - their hashes are equal.", context)
                 }
             } else {
                 groups.add(group)
-                statements[key] = LogCall(messageString, level, group, position)
-                call.range.isPresent
+                statements[key] = logCall
             }
         }
     }
 
     private val statements: MutableMap<Int, LogCall> = mutableMapOf()
     private val groups: MutableSet<LogGroup> = mutableSetOf()
-    private var fileName: String = ""
 
-    fun processClass(unit: CompilationUnit, fileName: String) {
-        this.fileName = fileName
-        protoLogCallVisitor.process(unit, this, fileName)
+    fun findLogCalls(unit: CompilationUnit, fileName: String): List<Pair<LogCall, ParsingContext>> {
+        val calls = mutableListOf<Pair<LogCall, ParsingContext>>()
+        val visitor = object : ProtoLogCallVisitor {
+            override fun processCall(
+                call: MethodCallExpr,
+                messageString: String,
+                level: LogLevel,
+                group: LogGroup
+            ) {
+                val logCall = LogCall(messageString, level, group, fileName)
+                val context = ParsingContext(fileName, call)
+                calls.add(logCall to context)
+            }
+        }
+        processor.process(unit, visitor, fileName)
+
+        return calls
+    }
+
+    fun addLogCalls(calls: List<Pair<LogCall, ParsingContext>>) {
+        calls.forEach { (logCall, context) ->
+            addLogCall(logCall, context)
+        }
     }
 
     fun build(): String {
@@ -101,5 +114,7 @@
         val logLevel: LogLevel,
         val logGroup: LogGroup,
         val position: String
-    )
+    ) {
+        fun key() = CodeUtils.hash(position, messageString, logLevel, logGroup)
+    }
 }
diff --git a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
index 615712e..cf36651c 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
@@ -30,6 +30,7 @@
         )
         private const val TEST_PROTOLOG_CLASS = "com.android.server.wm.ProtoLog"
         private const val TEST_PROTOLOGIMPL_CLASS = "com.android.server.wm.ProtoLogImpl"
+        private const val TEST_PROTOLOGCACHE_CLASS = "com.android.server.wm.ProtoLog\$Cache"
         private const val TEST_PROTOLOGGROUP_CLASS = "com.android.server.wm.ProtoLogGroup"
         private const val TEST_PROTOLOGGROUP_JAR = "out/soong/.intermediates/frameworks/base/" +
                 "services/core/services.core.wm.protologgroups/android_common/javac/" +
@@ -56,6 +57,7 @@
     fun transformClasses() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -73,6 +75,7 @@
     fun transformClasses_noProtoLogClass() {
         val testLine = "transform-protolog-calls " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -82,6 +85,17 @@
     @Test(expected = InvalidCommandException::class)
     fun transformClasses_noProtoLogImplClass() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
+                "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
+                "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
+                "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
+        CommandOptions(testLine.split(' ').toTypedArray())
+    }
+
+    @Test(expected = InvalidCommandException::class)
+    fun transformClasses_noProtoLogCacheClass() {
+        val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
+                "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -92,6 +106,7 @@
     fun transformClasses_noProtoLogGroupClass() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
         CommandOptions(testLine.split(' ').toTypedArray())
@@ -101,6 +116,7 @@
     fun transformClasses_noProtoLogGroupJar() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
         CommandOptions(testLine.split(' ').toTypedArray())
@@ -110,6 +126,7 @@
     fun transformClasses_noOutJar() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 TEST_JAVA_SRC.joinToString(" ")
@@ -120,6 +137,7 @@
     fun transformClasses_noJavaInput() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR"
@@ -130,6 +148,7 @@
     fun transformClasses_invalidProtoLogClass() {
         val testLine = "transform-protolog-calls --protolog-class invalid " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -140,6 +159,18 @@
     fun transformClasses_invalidProtoLogImplClass() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class invalid " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
+                "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
+                "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
+                "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
+        CommandOptions(testLine.split(' ').toTypedArray())
+    }
+
+    @Test(expected = InvalidCommandException::class)
+    fun transformClasses_invalidProtoLogCacheClass() {
+        val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
+                "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class invalid " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -150,6 +181,7 @@
     fun transformClasses_invalidProtoLogGroupClass() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class invalid " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -160,6 +192,7 @@
     fun transformClasses_invalidProtoLogGroupJar() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar invalid.txt " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -170,6 +203,7 @@
     fun transformClasses_invalidOutJar() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar invalid.db ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -180,6 +214,7 @@
     fun transformClasses_invalidJavaInput() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR invalid.py"
@@ -190,6 +225,7 @@
     fun transformClasses_unknownParam() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--unknown test --protolog-impl-class $TEST_PROTOLOGIMPL_CLASS " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
@@ -200,6 +236,7 @@
     fun transformClasses_noValue() {
         val testLine = "transform-protolog-calls --protolog-class $TEST_PROTOLOG_CLASS " +
                 "--protolog-impl-class " +
+                "--protolog-cache-class $TEST_PROTOLOGCACHE_CLASS " +
                 "--loggroups-class $TEST_PROTOLOGGROUP_CLASS " +
                 "--loggroups-jar $TEST_PROTOLOGGROUP_JAR " +
                 "--output-srcjar $TEST_SRC_JAR ${TEST_JAVA_SRC.joinToString(" ")}"
diff --git a/tools/protologtool/tests/com/android/protolog/tool/ProtoLogToolTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ProtoLogToolTest.kt
new file mode 100644
index 0000000..ea9a58d
--- /dev/null
+++ b/tools/protologtool/tests/com/android/protolog/tool/ProtoLogToolTest.kt
@@ -0,0 +1,52 @@
+/*
+ * 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.protolog.tool
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class ProtoLogToolTest {
+
+    @Test
+    fun generateLogGroupCache() {
+        val groups = mapOf(
+                "GROUP1" to LogGroup("GROUP1", true, true, "TAG1"),
+                "GROUP2" to LogGroup("GROUP2", true, true, "TAG2")
+        )
+        val code = ProtoLogTool.generateLogGroupCache("org.example", "ProtoLog\$Cache",
+                groups, "org.example.ProtoLogImpl", "org.example.ProtoLogGroups")
+
+        assertEquals("""
+            package org.example;
+
+            public class ProtoLog${'$'}Cache {
+                public static boolean GROUP1_enabled = false;
+                public static boolean GROUP2_enabled = false;
+
+                static {
+                    org.example.ProtoLogImpl.sCacheUpdater = ProtoLog${'$'}Cache::update;
+                    update();
+                }
+
+                static void update() {
+                    GROUP1_enabled = org.example.ProtoLogImpl.isEnabled(org.example.ProtoLogGroups.GROUP1);
+                    GROUP2_enabled = org.example.ProtoLogImpl.isEnabled(org.example.ProtoLogGroups.GROUP2);
+                }
+            }
+        """.trimIndent(), code)
+    }
+}
\ No newline at end of file
diff --git a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
index e746300..6f5955c 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
@@ -78,7 +78,7 @@
 
             class Test {
                 void test() {
-                    if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); }
                 }
             }
             """.trimIndent()
@@ -88,7 +88,7 @@
 
             class Test {
                 void test() {
-                    if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, 1780316587, 9, "test %d %f " + "abc %s\n test", protoLogParam0, protoLogParam1, protoLogParam2); 
+                    if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, 1780316587, 9, "test %d %f " + "abc %s\n test", protoLogParam0, protoLogParam1, protoLogParam2); 
             
             }
                 }
@@ -100,8 +100,8 @@
 
             class Test {
                 void test() {
-                    if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); } /* ProtoLog.w(TEST_GROUP, "test %d %f", 100, 0.1); */ if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); }
-                    if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); } /* ProtoLog.w(TEST_GROUP, "test %d %f", 100, 0.1); */ if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, "test %d %f", protoLogParam0, protoLogParam1); }
                 }
             }
             """.trimIndent()
@@ -111,7 +111,7 @@
 
             class Test {
                 void test() {
-                    if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { org.example.ProtoLogImpl.w(TEST_GROUP, -1741986185, 0, "test", (Object[]) null); }
+                    if (org.example.ProtoLogCache.TEST_GROUP_enabled) { org.example.ProtoLogImpl.w(TEST_GROUP, -1741986185, 0, "test", (Object[]) null); }
                 }
             }
             """.trimIndent()
@@ -121,7 +121,7 @@
 
             class Test {
                 void test() {
-                    if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, null, protoLogParam0, protoLogParam1); }
+                    if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; org.example.ProtoLogImpl.w(TEST_GROUP, 1698911065, 9, null, protoLogParam0, protoLogParam1); }
                 }
             }
             """.trimIndent()
@@ -131,7 +131,7 @@
 
             class Test {
                 void test() {
-                    if (org.example.ProtoLogImpl.isEnabled(TEST_GROUP)) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, 1780316587, 9, null, protoLogParam0, protoLogParam1, protoLogParam2); 
+                    if (org.example.ProtoLogCache.TEST_GROUP_enabled) { long protoLogParam0 = 100; double protoLogParam1 = 0.1; String protoLogParam2 = String.valueOf("test"); org.example.ProtoLogImpl.w(TEST_GROUP, 1780316587, 9, null, protoLogParam0, protoLogParam1, protoLogParam2); 
             
             }
                 }
@@ -165,8 +165,9 @@
     }
 
     private val processor: ProtoLogCallProcessor = Mockito.mock(ProtoLogCallProcessor::class.java)
-    private val implPath = "org.example.ProtoLogImpl"
-    private val sourceJarWriter = SourceTransformer(implPath, processor)
+    private val implName = "org.example.ProtoLogImpl"
+    private val cacheName = "org.example.ProtoLogCache"
+    private val sourceJarWriter = SourceTransformer(implName, cacheName, processor)
 
     private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
 
@@ -191,8 +192,7 @@
         val ifStmts = code.findAll(IfStmt::class.java)
         assertEquals(1, ifStmts.size)
         val ifStmt = ifStmts[0]
-        assertEquals("$implPath.${Constants.IS_ENABLED_METHOD}(TEST_GROUP)",
-                ifStmt.condition.toString())
+        assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString())
         assertFalse(ifStmt.elseStmt.isPresent)
         assertEquals(3, ifStmt.thenStmt.childNodes.size)
         val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr
@@ -234,8 +234,7 @@
         val ifStmts = code.findAll(IfStmt::class.java)
         assertEquals(3, ifStmts.size)
         val ifStmt = ifStmts[1]
-        assertEquals("$implPath.${Constants.IS_ENABLED_METHOD}(TEST_GROUP)",
-                ifStmt.condition.toString())
+        assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString())
         assertFalse(ifStmt.elseStmt.isPresent)
         assertEquals(3, ifStmt.thenStmt.childNodes.size)
         val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr
@@ -273,8 +272,7 @@
         val ifStmts = code.findAll(IfStmt::class.java)
         assertEquals(1, ifStmts.size)
         val ifStmt = ifStmts[0]
-        assertEquals("$implPath.${Constants.IS_ENABLED_METHOD}(TEST_GROUP)",
-                ifStmt.condition.toString())
+        assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString())
         assertFalse(ifStmt.elseStmt.isPresent)
         assertEquals(4, ifStmt.thenStmt.childNodes.size)
         val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[1] as MethodCallExpr
@@ -311,8 +309,7 @@
         val ifStmts = code.findAll(IfStmt::class.java)
         assertEquals(1, ifStmts.size)
         val ifStmt = ifStmts[0]
-        assertEquals("$implPath.${Constants.IS_ENABLED_METHOD}(TEST_GROUP)",
-                ifStmt.condition.toString())
+        assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString())
         assertFalse(ifStmt.elseStmt.isPresent)
         assertEquals(1, ifStmt.thenStmt.childNodes.size)
         val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr
@@ -346,8 +343,7 @@
         val ifStmts = code.findAll(IfStmt::class.java)
         assertEquals(1, ifStmts.size)
         val ifStmt = ifStmts[0]
-        assertEquals("$implPath.${Constants.IS_ENABLED_METHOD}(TEST_GROUP)",
-                ifStmt.condition.toString())
+        assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString())
         assertFalse(ifStmt.elseStmt.isPresent)
         assertEquals(3, ifStmt.thenStmt.childNodes.size)
         val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[0] as MethodCallExpr
@@ -385,8 +381,7 @@
         val ifStmts = code.findAll(IfStmt::class.java)
         assertEquals(1, ifStmts.size)
         val ifStmt = ifStmts[0]
-        assertEquals("$implPath.${Constants.IS_ENABLED_METHOD}(TEST_GROUP)",
-                ifStmt.condition.toString())
+        assertEquals("$cacheName.TEST_GROUP_enabled", ifStmt.condition.toString())
         assertFalse(ifStmt.elseStmt.isPresent)
         assertEquals(4, ifStmt.thenStmt.childNodes.size)
         val methodCall = ifStmt.thenStmt.findAll(MethodCallExpr::class.java)[1] as MethodCallExpr
diff --git a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt
index 2b6abcd..a24761a 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/ViewerConfigBuilderTest.kt
@@ -17,8 +17,7 @@
 package com.android.protolog.tool
 
 import com.android.json.stream.JsonReader
-import com.github.javaparser.ast.CompilationUnit
-import com.github.javaparser.ast.expr.MethodCallExpr
+import com.android.protolog.tool.ViewerConfigBuilder.LogCall
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.mockito.Mockito
@@ -34,14 +33,12 @@
         private val GROUP1 = LogGroup("TEST_GROUP", true, true, TAG1)
         private val GROUP2 = LogGroup("DEBUG_GROUP", true, true, TAG2)
         private val GROUP3 = LogGroup("DEBUG_GROUP", true, true, TAG2)
+        private val GROUP_DISABLED = LogGroup("DEBUG_GROUP", false, true, TAG2)
+        private val GROUP_TEXT_DISABLED = LogGroup("DEBUG_GROUP", true, false, TAG2)
         private const val PATH = "/tmp/test.java"
     }
 
-    private val processor: ProtoLogCallProcessor = Mockito.mock(ProtoLogCallProcessor::class.java)
-    private val configBuilder = ViewerConfigBuilder(processor)
-    private val dummyCompilationUnit = CompilationUnit()
-
-    private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
+    private val configBuilder = ViewerConfigBuilder(Mockito.mock(ProtoLogCallProcessor::class.java))
 
     private fun parseConfig(json: String): Map<Int, ViewerConfigParser.ConfigEntry> {
         return ViewerConfigParser().parseConfig(JsonReader(StringReader(json)))
@@ -49,22 +46,10 @@
 
     @Test
     fun processClass() {
-        Mockito.`when`(processor.process(any(CompilationUnit::class.java),
-                any(ProtoLogCallVisitor::class.java), any(String::class.java)))
-                .thenAnswer { invocation ->
-            val visitor = invocation.arguments[1] as ProtoLogCallVisitor
-
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST2.messageString, LogLevel.DEBUG,
-                    GROUP2)
-            visitor.processCall(MethodCallExpr(), TEST3.messageString, LogLevel.ERROR,
-                    GROUP3)
-
-            invocation.arguments[0] as CompilationUnit
-        }
-
-        configBuilder.processClass(dummyCompilationUnit, PATH)
+        configBuilder.addLogCalls(listOf(
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP2, PATH),
+                LogCall(TEST3.messageString, LogLevel.ERROR, GROUP3, PATH)).withContext())
 
         val parsedConfig = parseConfig(configBuilder.build())
         assertEquals(3, parsedConfig.size)
@@ -78,22 +63,10 @@
 
     @Test
     fun processClass_nonUnique() {
-        Mockito.`when`(processor.process(any(CompilationUnit::class.java),
-                any(ProtoLogCallVisitor::class.java), any(String::class.java)))
-                .thenAnswer { invocation ->
-            val visitor = invocation.arguments[1] as ProtoLogCallVisitor
-
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-
-            invocation.arguments[0] as CompilationUnit
-        }
-
-        configBuilder.processClass(dummyCompilationUnit, PATH)
+        configBuilder.addLogCalls(listOf(
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH)).withContext())
 
         val parsedConfig = parseConfig(configBuilder.build())
         assertEquals(1, parsedConfig.size)
@@ -103,28 +76,19 @@
 
     @Test
     fun processClass_disabled() {
-        Mockito.`when`(processor.process(any(CompilationUnit::class.java),
-                any(ProtoLogCallVisitor::class.java), any(String::class.java)))
-                .thenAnswer { invocation ->
-            val visitor = invocation.arguments[1] as ProtoLogCallVisitor
-
-            visitor.processCall(MethodCallExpr(), TEST1.messageString, LogLevel.INFO,
-                    GROUP1)
-            visitor.processCall(MethodCallExpr(), TEST2.messageString, LogLevel.DEBUG,
-                    LogGroup("DEBUG_GROUP", false, true, TAG2))
-            visitor.processCall(MethodCallExpr(), TEST3.messageString, LogLevel.ERROR,
-                    LogGroup("DEBUG_GROUP", true, false, TAG2))
-
-            invocation.arguments[0] as CompilationUnit
-        }
-
-        configBuilder.processClass(dummyCompilationUnit, PATH)
+        configBuilder.addLogCalls(listOf(
+                LogCall(TEST1.messageString, LogLevel.INFO, GROUP1, PATH),
+                LogCall(TEST2.messageString, LogLevel.DEBUG, GROUP_DISABLED, PATH),
+                LogCall(TEST3.messageString, LogLevel.ERROR, GROUP_TEXT_DISABLED, PATH))
+                .withContext())
 
         val parsedConfig = parseConfig(configBuilder.build())
         assertEquals(2, parsedConfig.size)
-        assertEquals(TEST1, parsedConfig[CodeUtils.hash(PATH, TEST1.messageString,
-	           LogLevel.INFO, GROUP1)])
-        assertEquals(TEST3, parsedConfig[CodeUtils.hash(PATH, TEST3.messageString,
-	           LogLevel.ERROR, LogGroup("DEBUG_GROUP", true, false, TAG2))])
+        assertEquals(TEST1, parsedConfig[CodeUtils.hash(
+                PATH, TEST1.messageString, LogLevel.INFO, GROUP1)])
+        assertEquals(TEST3, parsedConfig[CodeUtils.hash(
+                PATH, TEST3.messageString, LogLevel.ERROR, GROUP_TEXT_DISABLED)])
     }
+
+    private fun List<LogCall>.withContext() = map { it to ParsingContext() }
 }
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 4ce4406..c08f9b0 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -95,7 +95,7 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "libstatslog",
     host_supported: true,
     generated_sources: ["statslog.cpp"],
diff --git a/core/java/android/app/timedetector/TimeSignal.aidl b/wifi/java/android/net/wifi/IScanResultsListener.aidl
similarity index 70%
copy from core/java/android/app/timedetector/TimeSignal.aidl
copy to wifi/java/android/net/wifi/IScanResultsListener.aidl
index d2ec357..bec74a6 100644
--- a/core/java/android/app/timedetector/TimeSignal.aidl
+++ b/wifi/java/android/net/wifi/IScanResultsListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,6 +14,14 @@
  * limitations under the License.
  */
 
-package android.app.timedetector;
+package android.net.wifi;
 
-parcelable TimeSignal;
\ No newline at end of file
+/**
+ * Interface for Wi-Fi scan result available callback.
+ *
+ * @hide
+ */
+oneway interface IScanResultsListener
+{
+    void onScanResultsAvailable();
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index b7e1094..19be132 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -28,6 +28,7 @@
 import android.net.wifi.IDppCallback;
 import android.net.wifi.ILocalOnlyHotspotCallback;
 import android.net.wifi.INetworkRequestMatchCallback;
+import android.net.wifi.IScanResultsListener;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.ITxPacketCountListener;
@@ -93,6 +94,8 @@
 
     boolean disableNetwork(int netId, String packageName);
 
+    void allowAutojoin(int netId, boolean choice);
+
     boolean startScan(String packageName);
 
     List<ScanResult> getScanResults(String callingPackage);
@@ -227,4 +230,8 @@
     oneway void forget(int netId, in IBinder binder, in IActionListener listener, int callbackIdentifier);
 
     oneway void getTxPacketCount(String packageName, in IBinder binder, in ITxPacketCountListener listener, int callbackIdentifier);
+
+    void registerScanResultsListener(in IBinder binder, in IScanResultsListener Listener, int listenerIdentifier);
+
+    void unregisterScanResultsListener(int listenerIdentifier);
 }
diff --git a/wifi/java/android/net/wifi/IWifiScanner.aidl b/wifi/java/android/net/wifi/IWifiScanner.aidl
index 3984934..114c732 100644
--- a/wifi/java/android/net/wifi/IWifiScanner.aidl
+++ b/wifi/java/android/net/wifi/IWifiScanner.aidl
@@ -26,5 +26,5 @@
 {
     Messenger getMessenger();
 
-    Bundle getAvailableChannels(int band);
+    Bundle getAvailableChannels(int band, String packageName);
 }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 2afb14a..3bedddc 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -735,6 +735,14 @@
      */
     public int userApproved = USER_UNSPECIFIED;
 
+    /**
+     * @hide
+     * Auto-join is allowed by user for this network.
+     * Default true.
+     */
+    @SystemApi
+    public boolean allowAutojoin = true;
+
     /** The Below RSSI thresholds are used to configure AutoJoin
      *  - GOOD/LOW/BAD thresholds are used so as to calculate link score
      *  - UNWANTED_SOFT are used by the blacklisting logic so as to handle
@@ -2022,6 +2030,7 @@
         if (updateIdentifier != null) sbuf.append(" updateIdentifier=" + updateIdentifier);
         sbuf.append(" lcuid=" + lastConnectUid);
         sbuf.append(" userApproved=" + userApprovedAsString(userApproved));
+        sbuf.append(" allowAutojoin=" + allowAutojoin);
         sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected);
         sbuf.append(" ");
 
@@ -2421,6 +2430,7 @@
             numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
             numAssociation = source.numAssociation;
             userApproved = source.userApproved;
+            allowAutojoin = source.allowAutojoin;
             numNoInternetAccessReports = source.numNoInternetAccessReports;
             noInternetAccessExpected = source.noInternetAccessExpected;
             creationTime = source.creationTime;
@@ -2496,6 +2506,7 @@
         dest.writeInt(numScorerOverrideAndSwitchedNetwork);
         dest.writeInt(numAssociation);
         dest.writeInt(userApproved);
+        dest.writeBoolean(allowAutojoin);
         dest.writeInt(numNoInternetAccessReports);
         dest.writeInt(noInternetAccessExpected ? 1 : 0);
         dest.writeInt(shared ? 1 : 0);
@@ -2571,6 +2582,7 @@
                 config.numScorerOverrideAndSwitchedNetwork = in.readInt();
                 config.numAssociation = in.readInt();
                 config.userApproved = in.readInt();
+                config.allowAutojoin = in.readBoolean();
                 config.numNoInternetAccessReports = in.readInt();
                 config.noInternetAccessExpected = in.readInt() != 0;
                 config.shared = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 0b55794..62ba95d 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -27,6 +28,8 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -34,7 +37,7 @@
 import java.util.Locale;
 
 /**
- * Describes the state of any Wifi connection that is active or
+ * Describes the state of any Wi-Fi connection that is active or
  * is in the process of being set up.
  */
 public class WifiInfo implements Parcelable {
@@ -96,6 +99,47 @@
     private int mRssi;
 
     /**
+     * Wi-Fi unknown technology
+     */
+    public static final int WIFI_TECHNOLOGY_UNKNOWN = 0;
+
+    /**
+     * Wi-Fi 802.11a/b/g
+     */
+    public static final int WIFI_TECHNOLOGY_LEGACY = 1;
+
+    /**
+     * Wi-Fi 802.11n
+     */
+    public static final int WIFI_TECHNOLOGY_11N = 4;
+
+    /**
+     * Wi-Fi 802.11ac
+     */
+    public static final int WIFI_TECHNOLOGY_11AC = 5;
+
+    /**
+     * Wi-Fi 802.11ax
+     */
+    public static final int WIFI_TECHNOLOGY_11AX = 6;
+
+    /** @hide */
+    @IntDef(prefix = { "WIFI_TECHNOLOGY_" }, value = {
+            WIFI_TECHNOLOGY_UNKNOWN,
+            WIFI_TECHNOLOGY_LEGACY,
+            WIFI_TECHNOLOGY_11N,
+            WIFI_TECHNOLOGY_11AC,
+            WIFI_TECHNOLOGY_11AX
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface WifiTechnology{}
+
+    /**
+     * Wi-Fi technology for the connection
+     */
+    private @WifiTechnology int mWifiTechnology;
+
+    /**
      * The unit in which links speeds are expressed.
      */
     public static final String LINK_SPEED_UNITS = "Mbps";
@@ -286,6 +330,7 @@
             txSuccessRate = source.txSuccessRate;
             rxSuccessRate = source.rxSuccessRate;
             score = source.score;
+            mWifiTechnology = source.mWifiTechnology;
         }
     }
 
@@ -374,6 +419,22 @@
     }
 
     /**
+     * Sets the Wi-Fi technology
+     * @hide
+     */
+    public void setWifiTechnology(@WifiTechnology int wifiTechnology) {
+        mWifiTechnology = wifiTechnology;
+    }
+
+    /**
+     * Get connection Wi-Fi technology
+     * @return the connection Wi-Fi technology
+     */
+    public @WifiTechnology int getWifiTechnology() {
+        return mWifiTechnology;
+    }
+
+    /**
      * Returns the current link speed in {@link #LINK_SPEED_UNITS}.
      * @return the link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
      * @see #LINK_SPEED_UNITS
@@ -679,6 +740,7 @@
                 .append(", MAC: ").append(mMacAddress == null ? none : mMacAddress)
                 .append(", Supplicant state: ")
                 .append(mSupplicantState == null ? none : mSupplicantState)
+                .append(", Wi-Fi technology: ").append(mWifiTechnology)
                 .append(", RSSI: ").append(mRssi)
                 .append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS)
                 .append(", Tx Link speed: ").append(mTxLinkSpeed).append(LINK_SPEED_UNITS)
@@ -734,6 +796,7 @@
         dest.writeString(mNetworkSuggestionOrSpecifierPackageName);
         dest.writeString(mFqdn);
         dest.writeString(mProviderFriendlyName);
+        dest.writeInt(mWifiTechnology);
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -775,6 +838,7 @@
                 info.mNetworkSuggestionOrSpecifierPackageName = in.readString();
                 info.mFqdn = in.readString();
                 info.mProviderFriendlyName = in.readString();
+                info.mWifiTechnology = in.readInt();
                 return info;
             }
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 5496e83..f626b0c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -38,6 +38,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.NetworkStack;
 import android.net.wifi.hotspot2.IProvisioningCallback;
 import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
@@ -529,19 +530,25 @@
     @SystemApi
     public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
     /**
-     * The interface used for the softap.
+     * The lookup key for a String extra that stores the interface name used for the Soft AP.
+     * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}.
+     * Retrieve its value with {@link android.content.Intent#getStringExtra(String)}.
      *
      * @hide
      */
-    public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "wifi_ap_interface_name";
+    @SystemApi
+    public static final String EXTRA_WIFI_AP_INTERFACE_NAME =
+            "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME";
     /**
-     * The intended ip mode for this softap.
-     * @see #IFACE_IP_MODE_TETHERED
-     * @see #IFACE_IP_MODE_LOCAL_ONLY
+     * The lookup key for an int extra that stores the intended IP mode for this Soft AP.
+     * One of {@link #IFACE_IP_MODE_TETHERED} or {@link #IFACE_IP_MODE_LOCAL_ONLY}.
+     * This extra is included in the broadcast {@link #WIFI_AP_STATE_CHANGED_ACTION}.
+     * Retrieve its value with {@link android.content.Intent#getIntExtra(String, int)}.
      *
      * @hide
      */
-    public static final String EXTRA_WIFI_AP_MODE = "wifi_ap_mode";
+    @SystemApi
+    public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE";
 
     /** @hide */
     @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = {
@@ -647,6 +654,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int IFACE_IP_MODE_UNSPECIFIED = -1;
 
     /**
@@ -656,6 +664,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0;
 
     /**
@@ -665,6 +674,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int IFACE_IP_MODE_TETHERED = 1;
 
     /**
@@ -674,6 +684,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int IFACE_IP_MODE_LOCAL_ONLY = 2;
 
     /**
@@ -2661,16 +2672,21 @@
     /**
      * Call allowing ConnectivityService to update WifiService with interface mode changes.
      *
-     * The possible modes include: {@link #IFACE_IP_MODE_TETHERED},
-     *                             {@link #IFACE_IP_MODE_LOCAL_ONLY},
-     *                             {@link #IFACE_IP_MODE_CONFIGURATION_ERROR}
-     *
-     * @param ifaceName String name of the updated interface
-     * @param mode int representing the new mode
+     * @param ifaceName String name of the updated interface, or null to represent all interfaces
+     * @param mode int representing the new mode, one of:
+     *             {@link #IFACE_IP_MODE_TETHERED},
+     *             {@link #IFACE_IP_MODE_LOCAL_ONLY},
+     *             {@link #IFACE_IP_MODE_CONFIGURATION_ERROR},
+     *             {@link #IFACE_IP_MODE_UNSPECIFIED}
      *
      * @hide
      */
-    public void updateInterfaceIpState(String ifaceName, int mode) {
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
+    public void updateInterfaceIpState(@Nullable String ifaceName, @IfaceIpMode int mode) {
         try {
             IWifiManager iWifiManager = getIWifiManager();
             if (iWifiManager == null) {
@@ -2684,15 +2700,21 @@
     }
 
     /**
-     * Start SoftAp mode with the specified configuration.
-     * Note that starting in access point mode disables station
-     * mode operation
-     * @param wifiConfig SSID, security and channel details as
-     *        part of WifiConfiguration
-     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     * Start Soft AP (hotspot) mode with the specified configuration.
+     * Note that starting Soft AP mode may disable station mode operation if the device does not
+     * support concurrency.
+     * @param wifiConfig SSID, security and channel details as part of WifiConfiguration, or null to
+     *                   use the persisted Soft AP configuration that was previously set using
+     *                   {@link #setWifiApConfiguration(WifiConfiguration)}.
+     * @return {@code true} if the operation succeeded, {@code false} otherwise
      *
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
     public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {
         try {
             IWifiManager iWifiManager = getIWifiManager();
@@ -2710,6 +2732,11 @@
      *
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
     public boolean stopSoftAp() {
         try {
             IWifiManager iWifiManager = getIWifiManager();
@@ -3842,6 +3869,29 @@
     }
 
     /**
+     * Sets the user choice for allowing auto-join to a network.
+     * The updated choice will be made available through the updated config supplied by the
+     * CONFIGURED_NETWORKS_CHANGED broadcast.
+     *
+     * @param netId the id of the network to allow/disallow autojoin for.
+     * @param choice true to allow autojoin, false to disallow autojoin
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void allowAutojoin(int netId, boolean choice) {
+        try {
+            IWifiManager iWifiManager = getIWifiManager();
+            if (iWifiManager == null) {
+                throw new RemoteException("Wifi service is not running");
+            }
+            iWifiManager.allowAutojoin(netId, choice);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Disable ephemeral Network
      *
      * @param SSID, in the format of WifiConfiguration's SSID.
@@ -5104,4 +5154,90 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Base class for scan results listener. Should be implemented by applications and set when
+     * calling {@link WifiManager#addScanResultsListener(Executor, ScanResultsListener)}.
+     */
+    public interface ScanResultsListener {
+
+        /**
+         * Called when new scan results available.
+         * Caller should use {@link WifiManager#getScanResults()} to get the scan results.
+         */
+        void onScanResultsAvailable();
+    }
+
+    private class ScanResultsListenerProxy extends IScanResultsListener.Stub {
+        private final Executor mExecutor;
+        private final ScanResultsListener mListener;
+
+        ScanResultsListenerProxy(Executor executor, ScanResultsListener listener) {
+            mExecutor = executor;
+            mListener = listener;
+        }
+
+        @Override
+        public void onScanResultsAvailable() {
+            mExecutor.execute(mListener::onScanResultsAvailable);
+        }
+    }
+
+    /**
+     * Add a listener for Scan Results. See {@link ScanResultsListener}.
+     * Caller will receive the event when scan results are available.
+     * Caller should use {@link WifiManager#getScanResults()} to get the scan results.
+     * Caller can remove a previously registered listener using
+     * {@link WifiManager#removeScanResultsListener(ScanResultsListener)}
+     * <p>
+     * Applications should have the
+     * {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers
+     * without the permission will trigger a {@link java.lang.SecurityException}.
+     * <p>
+     *
+     * @param executor  The executor to execute the listener of the {@code listener} object.
+     * @param listener listener for Scan Results events
+     */
+
+    @RequiresPermission(ACCESS_WIFI_STATE)
+    public void addScanResultsListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull ScanResultsListener listener) {
+        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
+        if (executor == null) throw new IllegalArgumentException("executor cannot be null");
+        Log.v(TAG, "addScanResultsListener: listener=" + listener + ", executor=" + executor);
+        try {
+            IWifiManager iWifiManager = getIWifiManager();
+            if (iWifiManager == null) {
+                throw new RemoteException("Wifi service is not running");
+            }
+            iWifiManager.registerScanResultsListener(
+                    new Binder(),
+                    new ScanResultsListenerProxy(executor, listener),
+                    mContext.getOpPackageName().hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Allow callers to remove a previously added listener. After calling this method,
+     * applications will no longer receive Scan Results events.
+     *
+     * @param listener listener to remove for Scan Results events
+     */
+    @RequiresPermission(ACCESS_WIFI_STATE)
+    public void removeScanResultsListener(@NonNull ScanResultsListener listener) {
+        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
+        Log.v(TAG, "removeScanResultsListener: listener=" + listener);
+
+        try {
+            IWifiManager iWifiManager = getIWifiManager();
+            if (iWifiManager == null) {
+                throw new RemoteException("Wifi service is not running");
+            }
+            iWifiManager.unregisterScanResultsListener(mContext.getOpPackageName().hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 6c2d7ff..ba9dd37 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -157,7 +157,8 @@
          */
         public @NonNull Builder setBssidPattern(
                 @NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
-            checkNotNull(baseAddress, mask);
+            checkNotNull(baseAddress);
+            checkNotNull(mask);
             mBssidPatternMatcher = Pair.create(baseAddress, mask);
             return this;
         }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 4262017..9b529ce 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityThread;
 import android.net.MacAddress;
+import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Process;
@@ -80,6 +81,10 @@
          */
         private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
         /**
+         * The passpoint config for use with Hotspot 2.0 network
+         */
+        private @Nullable PasspointConfiguration mPasspointConfiguration;
+        /**
          * This is a network that does not broadcast its SSID, so an
          * SSID-specific probe request must be used for scans.
          */
@@ -110,6 +115,7 @@
             mWpa3SaePassphrase = null;
             mWpa2EnterpriseConfig = null;
             mWpa3EnterpriseConfig = null;
+            mPasspointConfiguration = null;
             mIsHiddenSSID = false;
             mIsAppInteractionRequired = false;
             mIsUserInteractionRequired = false;
@@ -234,6 +240,24 @@
         }
 
         /**
+         * Set the associated Passpoint configuration for this network. Needed for authenticating
+         * to Hotspot 2.0 networks. See {@link PasspointConfiguration} for description.
+         *
+         * @param passpointConfig Instance of {@link PasspointConfiguration}.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if passpoint configuration is invalid.
+         */
+        public @NonNull Builder setPasspointConfig(
+                @NonNull PasspointConfiguration passpointConfig) {
+            checkNotNull(passpointConfig);
+            if (!passpointConfig.validate()) {
+                throw new IllegalArgumentException("Passpoint configuration is invalid");
+            }
+            mPasspointConfiguration = passpointConfig;
+            return this;
+        }
+
+        /**
          * Specifies whether this represents a hidden network.
          * <p>
          * <li>If not set, defaults to false (i.e not a hidden network).</li>
@@ -366,13 +390,24 @@
             numSecurityTypes += !TextUtils.isEmpty(mWpa3SaePassphrase) ? 1 : 0;
             numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0;
             numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0;
+            numSecurityTypes += mPasspointConfiguration != null ? 1 : 0;
             if (numSecurityTypes > 1) {
                 throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase,"
-                        + "setWpa3Passphrase, setWpa2EnterpriseConfig or setWpa3EnterpriseConfig"
-                        + " can be invoked for network specifier");
+                        + "setWpa3Passphrase, setWpa2EnterpriseConfig, setWpa3EnterpriseConfig"
+                        + "or setPasspointConfig can be invoked for network suggestion");
             }
         }
 
+        private WifiConfiguration buildWifiConfigurationForPasspoint() {
+            WifiConfiguration wifiConfiguration = new WifiConfiguration();
+            wifiConfiguration.FQDN = mPasspointConfiguration.getHomeSp().getFqdn();
+            wifiConfiguration.priority = mPriority;
+            wifiConfiguration.meteredOverride =
+                    mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
+                            : WifiConfiguration.METERED_OVERRIDE_NONE;
+            return wifiConfiguration;
+        }
+
         /**
          * Create a network suggestion object for use in
          * {@link WifiManager#addNetworkSuggestions(List)}.
@@ -384,29 +419,36 @@
          * </p>
          *
          * For example:
-         * To provide credentials for one open, one WPA2 and one WPA3 network with their
-         * corresponding SSID's:
+         * To provide credentials for one open, one WPA2, one WPA3 network with their
+         * corresponding SSID's and one with Passpoint config:
          *
          * <pre>{@code
          * final WifiNetworkSuggestion suggestion1 =
          *      new Builder()
          *      .setSsid("test111111")
-         *      .build()
+         *      .build();
          * final WifiNetworkSuggestion suggestion2 =
          *      new Builder()
          *      .setSsid("test222222")
          *      .setWpa2Passphrase("test123456")
-         *      .build()
+         *      .build();
          * final WifiNetworkSuggestion suggestion3 =
          *      new Builder()
          *      .setSsid("test333333")
          *      .setWpa3Passphrase("test6789")
-         *      .build()
+         *      .build();
+         * final PasspointConfiguration passpointConfig= new PasspointConfiguration();
+         * // configure passpointConfig to include a valid Passpoint configuration
+         * final WifiNetworkSuggestion suggestion4 =
+         *      new Builder()
+         *      .setPasspointConfig(passpointConfig)
+         *      .build();
          * final List<WifiNetworkSuggestion> suggestionsList =
          *      new ArrayList<WifiNetworkSuggestion> { {
          *          add(suggestion1);
          *          add(suggestion2);
          *          add(suggestion3);
+         *          add(suggestion4);
          *      } };
          * final WifiManager wifiManager =
          *      context.getSystemService(Context.WIFI_SERVICE);
@@ -419,21 +461,37 @@
          * @see WifiNetworkSuggestion
          */
         public @NonNull WifiNetworkSuggestion build() {
-            if (mSsid == null) {
-                throw new IllegalStateException("setSsid should be invoked for suggestion");
-            }
-            if (TextUtils.isEmpty(mSsid)) {
-                throw new IllegalStateException("invalid ssid for suggestion");
-            }
-            if (mBssid != null
-                    && (mBssid.equals(MacAddress.BROADCAST_ADDRESS)
-                    || mBssid.equals(MacAddress.ALL_ZEROS_ADDRESS))) {
-                throw new IllegalStateException("invalid bssid for suggestion");
-            }
             validateSecurityParams();
+            WifiConfiguration wifiConfiguration;
+            if (mPasspointConfiguration != null) {
+                if (mSsid != null) {
+                    throw new IllegalStateException("setSsid should not be invoked for suggestion "
+                            + "with Passpoint configuration");
+                }
+                if (mIsHiddenSSID) {
+                    throw new IllegalStateException("setIsHiddenSsid should not be invoked for "
+                            + "suggestion with Passpoint configuration");
+                }
+                wifiConfiguration = buildWifiConfigurationForPasspoint();
+
+            } else {
+                if (mSsid == null) {
+                    throw new IllegalStateException("setSsid should be invoked for suggestion");
+                }
+                if (TextUtils.isEmpty(mSsid)) {
+                    throw new IllegalStateException("invalid ssid for suggestion");
+                }
+                if (mBssid != null
+                        && (mBssid.equals(MacAddress.BROADCAST_ADDRESS)
+                        || mBssid.equals(MacAddress.ALL_ZEROS_ADDRESS))) {
+                    throw new IllegalStateException("invalid bssid for suggestion");
+                }
+                wifiConfiguration = buildWifiConfiguration();
+            }
 
             return new WifiNetworkSuggestion(
-                    buildWifiConfiguration(),
+                    wifiConfiguration,
+                    mPasspointConfiguration,
                     mIsAppInteractionRequired,
                     mIsUserInteractionRequired,
                     Process.myUid(),
@@ -448,6 +506,12 @@
     public final WifiConfiguration wifiConfiguration;
 
     /**
+     * Passpoint configuration for the provided network.
+     * @hide
+     */
+    public final PasspointConfiguration passpointConfiguration;
+
+    /**
      * Whether app needs to log in to captive portal to obtain Internet access.
      * @hide
      */
@@ -474,6 +538,7 @@
     /** @hide */
     public WifiNetworkSuggestion() {
         this.wifiConfiguration = null;
+        this.passpointConfiguration = null;
         this.isAppInteractionRequired = false;
         this.isUserInteractionRequired = false;
         this.suggestorUid = -1;
@@ -481,14 +546,16 @@
     }
 
     /** @hide */
-    public WifiNetworkSuggestion(@NonNull WifiConfiguration wifiConfiguration,
+    public WifiNetworkSuggestion(@NonNull WifiConfiguration networkConfiguration,
+                                 @Nullable PasspointConfiguration passpointConfiguration,
                                  boolean isAppInteractionRequired,
                                  boolean isUserInteractionRequired,
                                  int suggestorUid, @NonNull String suggestorPackageName) {
-        checkNotNull(wifiConfiguration);
+        checkNotNull(networkConfiguration);
         checkNotNull(suggestorPackageName);
+        this.wifiConfiguration = networkConfiguration;
+        this.passpointConfiguration = passpointConfiguration;
 
-        this.wifiConfiguration = wifiConfiguration;
         this.isAppInteractionRequired = isAppInteractionRequired;
         this.isUserInteractionRequired = isUserInteractionRequired;
         this.suggestorUid = suggestorUid;
@@ -501,6 +568,7 @@
                 public WifiNetworkSuggestion createFromParcel(Parcel in) {
                     return new WifiNetworkSuggestion(
                             in.readParcelable(null), // wifiConfiguration
+                            in.readParcelable(null), // PasspointConfiguration
                             in.readBoolean(), // isAppInteractionRequired
                             in.readBoolean(), // isUserInteractionRequired
                             in.readInt(), // suggestorUid
@@ -522,6 +590,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(wifiConfiguration, flags);
+        dest.writeParcelable(passpointConfiguration, flags);
         dest.writeBoolean(isAppInteractionRequired);
         dest.writeBoolean(isUserInteractionRequired);
         dest.writeInt(suggestorUid);
@@ -531,7 +600,8 @@
     @Override
     public int hashCode() {
         return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID,
-                wifiConfiguration.allowedKeyManagement, suggestorUid, suggestorPackageName);
+                wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN,
+                suggestorUid, suggestorPackageName);
     }
 
     /**
@@ -546,12 +616,17 @@
             return false;
         }
         WifiNetworkSuggestion lhs = (WifiNetworkSuggestion) obj;
-        return Objects.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID)
-                && Objects.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
+        if (this.passpointConfiguration == null ^ lhs.passpointConfiguration == null) {
+            return false;
+        }
+
+        return TextUtils.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID)
+                && TextUtils.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
                 && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
-                                  lhs.wifiConfiguration.allowedKeyManagement)
-                && suggestorUid == lhs.suggestorUid
-                && TextUtils.equals(suggestorPackageName, lhs.suggestorPackageName);
+                lhs.wifiConfiguration.allowedKeyManagement)
+                && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN)
+                && this.suggestorUid == lhs.suggestorUid
+                && TextUtils.equals(this.suggestorPackageName, lhs.suggestorPackageName);
     }
 
     @Override
@@ -559,6 +634,7 @@
         StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [")
                 .append(", SSID=").append(wifiConfiguration.SSID)
                 .append(", BSSID=").append(wifiConfiguration.BSSID)
+                .append(", FQDN=").append(wifiConfiguration.FQDN)
                 .append(", isAppInteractionRequired=").append(isAppInteractionRequired)
                 .append(", isUserInteractionRequired=").append(isUserInteractionRequired)
                 .append(", suggestorUid=").append(suggestorUid)
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 68948cb..21189a4 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -17,7 +17,9 @@
 package android.net.wifi;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -39,6 +41,8 @@
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.Protocol;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -51,26 +55,38 @@
 @SystemService(Context.WIFI_SCANNING_SERVICE)
 public class WifiScanner {
 
-    /** no band specified; use channel list instead */
-    public static final int WIFI_BAND_UNSPECIFIED = 0;      /* not specified */
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"WIFI_BAND_"}, value = {
+            WIFI_BAND_UNSPECIFIED,
+            WIFI_BAND_24_GHZ,
+            WIFI_BAND_5_GHZ,
+            WIFI_BAND_BOTH,
+            WIFI_BAND_5_GHZ_DFS_ONLY,
+            WIFI_BAND_24_GHZ_WITH_5GHZ_DFS,
+            WIFI_BAND_5_GHZ_WITH_DFS,
+            WIFI_BAND_BOTH_WITH_DFS})
+    public @interface WifiBand {}
 
+    /** no band specified; use channel list instead */
+    public static final int WIFI_BAND_UNSPECIFIED = 0;
     /** 2.4 GHz band */
-    public static final int WIFI_BAND_24_GHZ = 1;           /* 2.4 GHz band */
+    public static final int WIFI_BAND_24_GHZ = 1;
     /** 5 GHz band excluding DFS channels */
-    public static final int WIFI_BAND_5_GHZ = 2;            /* 5 GHz band without DFS channels */
+    public static final int WIFI_BAND_5_GHZ = 2;
+    /** Both 2.4 GHz band and 5 GHz band; no DFS channels */
+    public static final int WIFI_BAND_BOTH = 3;
     /** DFS channels from 5 GHz band only */
-    public static final int WIFI_BAND_5_GHZ_DFS_ONLY  = 4;  /* 5 GHz band DFS channels */
+    public static final int WIFI_BAND_5_GHZ_DFS_ONLY  = 4;
     /**
      * 2.4Ghz band + DFS channels from 5 GHz band only
      * @hide
      */
     public static final int WIFI_BAND_24_GHZ_WITH_5GHZ_DFS  = 5;
     /** 5 GHz band including DFS channels */
-    public static final int WIFI_BAND_5_GHZ_WITH_DFS  = 6;  /* 5 GHz band with DFS channels */
-    /** Both 2.4 GHz band and 5 GHz band; no DFS channels */
-    public static final int WIFI_BAND_BOTH = 3;             /* both bands without DFS channels */
+    public static final int WIFI_BAND_5_GHZ_WITH_DFS  = 6;
     /** Both 2.4 GHz band and 5 GHz band; with DFS channels */
-    public static final int WIFI_BAND_BOTH_WITH_DFS = 7;    /* both bands with DFS channels */
+    public static final int WIFI_BAND_BOTH_WITH_DFS = 7;
     /**
      * Max band value
      * @hide
@@ -78,9 +94,9 @@
     public static final int WIFI_BAND_MAX = 8;
 
     /** Minimum supported scanning period */
-    public static final int MIN_SCAN_PERIOD_MS = 1000;      /* minimum supported period */
+    public static final int MIN_SCAN_PERIOD_MS = 1000;
     /** Maximum supported scanning period */
-    public static final int MAX_SCAN_PERIOD_MS = 1024000;   /* maximum supported period */
+    public static final int MAX_SCAN_PERIOD_MS = 1024000;
 
     /** No Error */
     public static final int REASON_SUCCEEDED = 0;
@@ -109,13 +125,20 @@
     }
 
     /**
-     * gives you all the possible channels; channel is specified as an
-     * integer with frequency in MHz i.e. channel 1 is 2412
+     * Returns a list of all the possible channels for the given band(s).
+     *
+     * @param band one of the WifiScanner#WIFI_BAND_* constants, e.g. {@link #WIFI_BAND_24_GHZ}
+     * @return a list of all the frequencies, in MHz, for the given band(s) e.g. channel 1 is
+     * 2412, or null if an error occurred.
+     *
      * @hide
      */
-    public List<Integer> getAvailableChannels(int band) {
+    @SystemApi
+    @Nullable
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+    public List<Integer> getAvailableChannels(@WifiBand int band) {
         try {
-            Bundle bundle =  mService.getAvailableChannels(band);
+            Bundle bundle = mService.getAvailableChannels(band, mContext.getOpPackageName());
             return bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA);
         } catch (RemoteException e) {
             return null;
diff --git a/wifi/java/android/net/wifi/hotspot2/ConfigParser.java b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
index e8e8731..bb01365 100644
--- a/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
@@ -182,6 +182,12 @@
             throw new IOException("Passpoint profile missing credential");
         }
 
+        // Don't allow the installer to make changes to the update identifier. This is an
+        // indicator of an R2 (or newer) network.
+        if (config.getUpdateIdentifier() != Integer.MIN_VALUE) {
+            config.setUpdateIdentifier(Integer.MIN_VALUE);
+        }
+
         // Parse CA (Certificate Authority) certificate.
         byte[] caCertData = mimeParts.get(TYPE_CA_CERT);
         if (caCertData != null) {
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 557b7c9..e9aa076 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -65,6 +65,7 @@
      * Configurations under HomeSp subtree.
      */
     private HomeSp mHomeSp = null;
+
     /**
      * Set the Home SP (Service Provider) information.
      *
@@ -248,7 +249,10 @@
         mSubscriptionExpirationTimeInMillis = subscriptionExpirationTimeInMillis;
     }
     /**
-     * @hide
+     *  Utility method to get the time this subscription will expire. It is in the format of number
+     *  of milliseconds since January 1, 1970, 00:00:00 GMT.
+     *
+     *  @return The time this subscription will expire, or Long.MIN_VALUE to indicate unset value
      */
     public long getSubscriptionExpirationTimeInMillis() {
         return mSubscriptionExpirationTimeInMillis;
@@ -521,6 +525,8 @@
                 .append("\n");
         builder.append("UsageLimitDataLimit: ").append(mUsageLimitDataLimit).append("\n");
         builder.append("UsageLimitTimeLimit: ").append(mUsageLimitTimeLimitInMinutes).append("\n");
+        builder.append("Provisioned by a subscription server: ")
+                .append(isOsuProvisioned() ? "Yes" : "No").append("\n");
         if (mHomeSp != null) {
             builder.append("HomeSP Begin ---\n");
             builder.append(mHomeSp);
@@ -728,4 +734,14 @@
         }
         return true;
     }
+
+    /**
+     * Indicates if the Passpoint Configuration was provisioned by a subscription (OSU) server,
+     * which means that it's an R2 (or R3) profile.
+     *
+     * @return true if the Passpoint Configuration was provisioned by a subscription server.
+     */
+    public boolean isOsuProvisioned() {
+        return getUpdateIdentifier() != Integer.MIN_VALUE;
+    }
 }
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 4ca2a16..5e6c107 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -26,6 +26,7 @@
 import android.net.wifi.ILocalOnlyHotspotCallback;
 import android.net.wifi.INetworkRequestMatchCallback;
 import android.net.wifi.IOnWifiUsabilityStatsListener;
+import android.net.wifi.IScanResultsListener;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.ITxPacketCountListener;
@@ -167,6 +168,11 @@
     }
 
     @Override
+    public void allowAutojoin(int netId, boolean choice) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean startScan(String packageName) {
         throw new UnsupportedOperationException();
     }
@@ -515,4 +521,15 @@
             ITxPacketCountListener callback, int callbackIdentifier) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void registerScanResultsListener(
+            IBinder binder, IScanResultsListener listener, int listenerIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void unregisterScanResultsListener(int listenerIdentifier) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
index 56919c2..760c839 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
@@ -12,75 +12,75 @@
 OWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRtRnRaVDVJYjIx
 bFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1
 dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNB
-OFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklDQWdQQzlPYjJS
-bFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrWlJSRTQ4
-TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1MWF6d3ZWbUZz
-ZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0Fn
-SUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2ClpHVk9ZVzFs
-UGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpoYkhWbFBnb2dJ
-Q0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4VG05a1pUNEtJ
-Q0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVoYldVK0NpQWdJ
-Q0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhiRzA4CkwwNXZa
-R1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHljbVZrTG1OdmJU
-d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lD
-QWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThMMDV2WkdWT1lX
-MWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0ClpU
-NVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDVxWVcx
-bGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05
-a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BDOU9iMlJsVG1G
-dFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3dlZtRnNkV1Ur
-CkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0Fn
-SUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0Fn
-SUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1GdFpUNUZRVkJV
-ZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrTWpFOEwxWmhi
-SFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxQ
-Z29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2WkR3dlRtOWta
-VTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0VmpJOEwxWmhi
-SFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0Np
-QWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BF
-NXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
-QWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQa05sY25ScFpt
-bGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDU0TlRB
-NWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1
-dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1qVTJSbWx1WjJW
-eWNISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdVKwpNV1l4WmpG
+OFZtRnNkV1UrUlhoaGJYQnNaU0JPWlhSM2IzSnJQQzlXWVd4MVpUNEtJQ0FnCklDQWdJQ0E4TDA1
+dlpHVStDaUFnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStSbEZF
+VGp3dlRtOWsKWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4Vm1Gc2RXVSthRzkwYzNCdmRDNWxlR0Z0
+Y0d4bExtNWxkRHd2Vm1Gc2RXVStDaUFnSUNBZwpJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhP
+YjJSbFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbEp2WVcxcGJtZERiMjV6CmIzSjBhWFZ0
+VDBrOEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBqRXhNakl6TXl3ME5EVTFO
+alk4TDFaaGJIVmwKUGdvZ0lDQWdJQ0FnSUR3dlRtOWtaVDRLSUNBZ0lDQWdQQzlPYjJSbFBnb2dJ
+Q0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0E4VG05awpaVTVoYldVK1EzSmxaR1Z1ZEdsaGJEd3ZU
+bTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrClpVNWhi
+V1UrVW1WaGJHMDhMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbVY0WVcxd2JH
+VXVZMjl0UEM5V1lXeDEKWlQ0S0lDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEU1dlpH
+VStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrVlhObApjbTVoYldWUVlYTnpkMjl5WkR3dlRt
+OWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2ClpH
+Vk9ZVzFsUGxWelpYSnVZVzFsUEM5T2IyUmxUbUZ0WlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRlpoYkhW
+bFBuVnpaWEk4TDFaaGJIVmwKUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNB
+Z1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9iMlJsVG1GdApaVDVRWVhOemQyOXlaRHd2VG05
+a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gxWlQ1alIwWjZZek5rZG1OdFVUMDhMMVpo
+CmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFn
+SUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNUZRVkJOWlhSb2IyUThMMDV2WkdWT1lXMWxQZ29n
+SUNBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZwpJQ0E4VG05a1pVNWhiV1Ur
+UlVGUVZIbHdaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBqSXhQ
+QzlXCllXeDFaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThU
+bTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWcKSUNBOFRtOWtaVTVoYldVK1NXNXVaWEpOWlhSb2IyUThM
+MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gxWlQ1TgpVeTFEU0VGUUxWWXlQ
+QzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2Iy
+UmxQZ29nCklDQWdJQ0FnSUR3dlRtOWtaVDRLSUNBZ0lDQWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lD
+QWdJRHhPYjJSbFRtRnRaVDVFYVdkcGRHRnMKUTJWeWRHbG1hV05oZEdVOEwwNXZaR1ZPWVcxbFBn
+b2dJQ0FnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbApUbUZ0WlQ1RFpY
+SjBhV1pwWTJGMFpWUjVjR1U4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
+K2VEVXdPWFl6ClBDOVdZV3gxWlQ0S0lDQWdJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNB
+Z0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ0lDQTgKVG05a1pVNWhiV1UrUTJWeWRGTklRVEkxTmta
+cGJtZGxjbkJ5YVc1MFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaApiSFZsUGpG
 bU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZt
-TVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNBOEwwNXZaR1Ur
-Q2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0Fn
-UEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4VG05awpaVDRL
-SUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJ
-Q0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNBOEwwNXZa
-R1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2WkdWT1lXMWxQ
-a1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrTWpROApM
-MVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lD
-QWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQQzlOWjIxMFZI
-SmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXg1MDktY2Et
-Y2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFDUlVkSlRpQkRS
-VkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtRVWxNYkVaa2Qz
-cE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5UbFlLUWtGTlZF
-SXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpUazFxV1hkTlZF
-RTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5VVEJGZUUxSlNV
-Skpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMwTkJVVVZCQ25w
-dVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZYTldkVzFFWWxs
-SWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01TdHZSMWhhZGto
-M2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJVRkRaV1pXYW1v
-d2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJoU1FqZzFNVEpR
-UWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdKck1IVjVhM1Jr
-WW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtzM2FFUTRjRkIy
-WmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxhCmFYQllOREY0
-UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVXTTJreGRIRXdO
-R3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZHU1hkWU5IWnpP
-RUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFFYlVGR1NYZFlO
-SFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJkMFJuCldVUldV
-VkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldVakJVUWtGVmQw
-RjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZMDVCVVVWTVFs
-RkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZDamxIUlZBdmRX
-OW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNYZEpWV00zCmQy
-azNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1EwOTBhWE5rUW5F
-eWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JXMVdUQW94Y1VK
-S2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVFMXVWR3c0ZUVW
-WFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhwaFNFb3hkVlk0
-Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpGS1VDdHNlRllL
-YlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNSa1RrNTJRMWw2
-YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmtsRFFWUkZMUzB0
-TFMwSwotLXtib3VuZGFyeX0tLQo=
+TVdZeFpqRm1NV1l4ClpqRm1NV1l4WmpGbU1XWThMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlP
+YjJSbFBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWcKSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0Fn
+SUNBZ0lEeE9iMlJsVG1GdFpUNVRTVTA4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZwpQRTV2
+WkdVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFRtRnRaVDVKVFZOSlBDOU9iMlJsVG1GdFpUNEtJ
+Q0FnSUNBZ0lDQWdJQ0FnClBGWmhiSFZsUGpFeU16UTFOaW84TDFaaGJIVmxQZ29nSUNBZ0lDQWdJ
+Q0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVSsKQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9i
+MlJsVG1GdFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaApi
+SFZsUGpJelBDOVdZV3gxWlQ0S0lDQWdJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNBOEww
+NXZaR1UrQ2lBZ0lDQWdJRHd2ClRtOWtaVDRLSUNBZ0lEd3ZUbTlrWlQ0S0lDQThMMDV2WkdVK0Nq
+d3ZUV2R0ZEZSeVpXVSsKCi0te2JvdW5kYXJ5fQpDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL3gt
+eDUwOS1jYS1jZXJ0CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NAoKTFMwdExTMUNS
+VWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVUkxSRU5EUVdoRFowRjNTVUpCWjBsS1FV
+bE1iRVprZDNwTQpWblZ5VFVFd1IwTlRjVWRUU1dJelJGRkZRa04zVlVGTlFrbDRSVVJCVDBKblRs
+WUtRa0ZOVkVJd1ZrSlZRMEpFVVZSRmQwaG9ZMDVOClZGbDNUVlJGZVUxVVJURk5SRVV4VjJoalRr
+MXFXWGROVkVFMVRWUkZNVTFFUlRGWGFrRlRUVkpCZHdwRVoxbEVWbEZSUkVWM1pFWlIKVmtGblVU
+QkZlRTFKU1VKSmFrRk9RbWRyY1docmFVYzVkekJDUVZGRlJrRkJUME5CVVRoQlRVbEpRa05uUzBO
+QlVVVkJDbnB1UVZCVgplakkyVFhOaFpUUjNjelF6WTNwU05ERXZTakpSZEhKVFNWcFZTMjFXVlhO
+V2RXMUVZbGxJY2xCT2RsUllTMU5OV0VGalpYZFBVa1JSCldWZ0tVbkYyU0had2JqaERjMk5DTVN0
+dlIxaGFka2gzZUdvMGVsWXdWMHR2U3pKNlpWaHJZWFV6ZG1ONWJETklTVXQxY0VwbWNUSlUKUlVG
+RFpXWldhbW93ZEFwS1Z5dFlNelZRUjFkd09TOUlOWHBKVlU1V1RsWnFVemRWYlhNNE5FbDJTMmhT
+UWpnMU1USlFRamxWZVVoaApaMWhaVmxnMVIxZHdRV05XY0hsbWNteFNDa1pKT1ZGa2FHZ3JVR0py
+TUhWNWEzUmtZbVl2UTJSbVowaFBiMlZpY2xSMGQxSnNhazB3CmIwUjBXQ3N5UTNZMmFqQjNRa3Mz
+YUVRNGNGQjJaakVyZFhrS1IzcGplbWxuUVZVdk5FdDNOMlZhY1hsa1pqbENLelZTZFhCU0swbGEK
+YVhCWU5ERjRSV2xKY2t0U2QzRnBOVEUzVjFkNldHTnFZVWN5WTA1aVpqUTFNUXA0Y0VnMVVHNVdN
+Mmt4ZEhFd05HcE5SMUZWZWtaMwpTVVJCVVVGQ2J6UkhRVTFJTkhkSVVWbEVWbEl3VDBKQ1dVVkdT
+WGRZTkhaek9FSnBRbU5UWTI5a0NqVnViMXBJVWswNFJUUXJhVTFGClNVZEJNVlZrU1hkUk4wMUVi
+VUZHU1hkWU5IWnpPRUpwUW1OVFkyOWtOVzV2V2toU1RUaEZOQ3RwYjFKaGEwWkVRVk1LVFZKQmQw
+Um4KV1VSV1VWRkVSWGRrUmxGV1FXZFJNRVY0WjJkclFXZDFWVll6UkUxMFZ6WnpkMFJCV1VSV1Vq
+QlVRa0ZWZDBGM1JVSXZla0ZNUW1kTwpWZ3BJVVRoRlFrRk5RMEZSV1hkRVVWbEtTMjlhU1doMlkw
+NUJVVVZNUWxGQlJHZG5SVUpCUm1aUmNVOVVRVGRTZGpkTEsyeDFVVGR3CmJtRnpORUpaZDBoRkNq
+bEhSVkF2ZFc5b2RqWkxUM2t3VkVkUlJtSnlVbFJxUm05TVZrNUNPVUphTVhsdFRVUmFNQzlVU1hk
+SlZXTTMKZDJrM1lUaDBOVzFGY1ZsSU1UVXpkMWNLWVZkdmIybFRhbmxNVEdoMVNUUnpUbkpPUTA5
+MGFYTmtRbkV5Y2pKTlJsaDBObWd3YlVGUgpXVTlRZGpoU09FczNMMlpuVTNoSFJuRjZhSGxPYlcx
+V1RBb3hjVUpLYkdSNE16UlRjSGR6VkVGTVVWWlFZalJvUjNkS2VscG1jakZRClkzQkZVWGcyZUUx
+dVZHdzRlRVZYV2tVelRYTTVPWFZoVlhoaVVYRkpkMUoxQ2t4blFVOXJUa050V1RKdE9EbFdhSHBo
+U0VveGRWWTQKTlVGa1RTOTBSQ3RaYzIxc2JtNXFkRGxNVWtObGFtSkNhWEJxU1VkcVQxaHlaekZL
+VUN0c2VGWUtiWFZOTkhaSUsxQXZiV3h0ZUhOUQpVSG93WkRZMVlpdEZSMjFLV25CdlRHdFBMM1Jr
+VGs1MlExbDZha3B3VkVWWGNFVnpUelpPVFdoTFdXODlDaTB0TFMwdFJVNUVJRU5GClVsUkpSa2xE
+UVZSRkxTMHRMUzBLCi0te2JvdW5kYXJ5fS0tCg==
\ No newline at end of file
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
index a44b542..5b4e4cb 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
@@ -13,38 +13,38 @@
 ICAgICA8L1R5cGU+CiAgICA8L1JUUHJvcGVydGllcz4KICAgIDxOb2RlPgogICAgICA8Tm9kZU5h
 bWU+aTAwMTwvTm9kZU5hbWU+CiAgICAgIDxOb2RlPgogICAgICAgIDxOb2RlTmFtZT5Ib21lU1A8
 L05vZGVOYW1lPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPkZyaWVuZGx5TmFt
-ZTwvTm9kZU5hbWU+CiAgICAgICAgICA8VmFsdWU+Q2VudHVyeSBIb3VzZTwvVmFsdWU+CiAgICAg
-ICAgPC9Ob2RlPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPkZRRE48L05vZGVO
-YW1lPgogICAgICAgICAgPFZhbHVlPm1pNi5jby51azwvVmFsdWU+CiAgICAgICAgPC9Ob2RlPgog
-ICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlJvYW1pbmdDb25zb3J0aXVtT0k8L05v
-ZGVOYW1lPgogICAgICAgICAgPFZhbHVlPjExMjIzMyw0NDU1NjY8L1ZhbHVlPgogICAgICAgIDwv
-Tm9kZT4KICAgICAgPC9Ob2RlPgogICAgICA8Tm9kZT4KICAgICAgICA8Tm9kZU5hbWU+Q3JlZGVu
-dGlhbDwvTm9kZU5hbWU+CiAgICAgICAgPE5vZGU+CiAgICAgICAgICA8Tm9kZU5hbWU+UmVhbG08
-L05vZGVOYW1lPgogICAgICAgICAgPFZhbHVlPnNoYWtlbi5zdGlycmVkLmNvbTwvVmFsdWU+CiAg
-ICAgICAgPC9Ob2RlPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlVzZXJuYW1l
-UGFzc3dvcmQ8L05vZGVOYW1lPgogICAgICAgICAgPE5vZGU+CiAgICAgICAgICAgIDxOb2RlTmFt
-ZT5Vc2VybmFtZTwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxWYWx1ZT5qYW1lczwvVmFsdWU+CiAg
-ICAgICAgICA8L05vZGU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5vZGVOYW1lPlBh
-c3N3b3JkPC9Ob2RlTmFtZT4KICAgICAgICAgICAgPFZhbHVlPlltOXVaREF3Tnc9PTwvVmFsdWU+
-CiAgICAgICAgICA8L05vZGU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5vZGVOYW1l
-PkVBUE1ldGhvZDwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxOb2RlPgogICAgICAgICAgICAgIDxO
-b2RlTmFtZT5FQVBUeXBlPC9Ob2RlTmFtZT4KICAgICAgICAgICAgICA8VmFsdWU+MjE8L1ZhbHVl
-PgogICAgICAgICAgICA8L05vZGU+CiAgICAgICAgICAgIDxOb2RlPgogICAgICAgICAgICAgIDxO
-b2RlTmFtZT5Jbm5lck1ldGhvZDwvTm9kZU5hbWU+CiAgICAgICAgICAgICAgPFZhbHVlPk1TLUNI
-QVAtVjI8L1ZhbHVlPgogICAgICAgICAgICA8L05vZGU+CiAgICAgICAgICA8L05vZGU+CiAgICAg
-ICAgPC9Ob2RlPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPkRpZ2l0YWxDZXJ0
-aWZpY2F0ZTwvTm9kZU5hbWU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5vZGVOYW1l
-PkNlcnRpZmljYXRlVHlwZTwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxWYWx1ZT54NTA5djM8L1Zh
+ZTwvTm9kZU5hbWU+CiAgICAgICAgICA8VmFsdWU+RXhhbXBsZSBOZXR3b3JrPC9WYWx1ZT4KICAg
+ICAgICA8L05vZGU+CiAgICAgICAgPE5vZGU+CiAgICAgICAgICA8Tm9kZU5hbWU+RlFETjwvTm9k
+ZU5hbWU+CiAgICAgICAgICA8VmFsdWU+aG90c3BvdC5leGFtcGxlLm5ldDwvVmFsdWU+CiAgICAg
+ICAgPC9Ob2RlPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlJvYW1pbmdDb25z
+b3J0aXVtT0k8L05vZGVOYW1lPgogICAgICAgICAgPFZhbHVlPjExMjIzMyw0NDU1NjY8L1ZhbHVl
+PgogICAgICAgIDwvTm9kZT4KICAgICAgPC9Ob2RlPgogICAgICA8Tm9kZT4KICAgICAgICA8Tm9k
+ZU5hbWU+Q3JlZGVudGlhbDwvTm9kZU5hbWU+CiAgICAgICAgPE5vZGU+CiAgICAgICAgICA8Tm9k
+ZU5hbWU+UmVhbG08L05vZGVOYW1lPgogICAgICAgICAgPFZhbHVlPmV4YW1wbGUuY29tPC9WYWx1
+ZT4KICAgICAgICA8L05vZGU+CiAgICAgICAgPE5vZGU+CiAgICAgICAgICA8Tm9kZU5hbWU+VXNl
+cm5hbWVQYXNzd29yZDwvTm9kZU5hbWU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5v
+ZGVOYW1lPlVzZXJuYW1lPC9Ob2RlTmFtZT4KICAgICAgICAgICAgPFZhbHVlPnVzZXI8L1ZhbHVl
+PgogICAgICAgICAgPC9Ob2RlPgogICAgICAgICAgPE5vZGU+CiAgICAgICAgICAgIDxOb2RlTmFt
+ZT5QYXNzd29yZDwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxWYWx1ZT5jR0Z6YzNkdmNtUT08L1Zh
 bHVlPgogICAgICAgICAgPC9Ob2RlPgogICAgICAgICAgPE5vZGU+CiAgICAgICAgICAgIDxOb2Rl
-TmFtZT5DZXJ0U0hBMjU2RmluZ2VycHJpbnQ8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFsdWU+
-MWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYx
-ZjFmMWYxZjwvVmFsdWU+CiAgICAgICAgICA8L05vZGU+CiAgICAgICAgPC9Ob2RlPgogICAgICAg
-IDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlNJTTwvTm9kZU5hbWU+CiAgICAgICAgICA8Tm9k
-ZT4KICAgICAgICAgICAgPE5vZGVOYW1lPklNU0k8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFs
-dWU+aW1zaTwvVmFsdWU+CiAgICAgICAgICA8L05vZGU+CiAgICAgICAgICA8Tm9kZT4KICAgICAg
-ICAgICAgPE5vZGVOYW1lPkVBUFR5cGU8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFsdWU+MjQ8
-L1ZhbHVlPgogICAgICAgICAgPC9Ob2RlPgogICAgICAgIDwvTm9kZT4KICAgICAgPC9Ob2RlPgog
-ICAgPC9Ob2RlPgogIDwvTm9kZT4KPC9NZ210VHJlZT4K
+TmFtZT5FQVBNZXRob2Q8L05vZGVOYW1lPgogICAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAg
+ICA8Tm9kZU5hbWU+RUFQVHlwZTwvTm9kZU5hbWU+CiAgICAgICAgICAgICAgPFZhbHVlPjIxPC9W
+YWx1ZT4KICAgICAgICAgICAgPC9Ob2RlPgogICAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAg
+ICA8Tm9kZU5hbWU+SW5uZXJNZXRob2Q8L05vZGVOYW1lPgogICAgICAgICAgICAgIDxWYWx1ZT5N
+Uy1DSEFQLVYyPC9WYWx1ZT4KICAgICAgICAgICAgPC9Ob2RlPgogICAgICAgICAgPC9Ob2RlPgog
+ICAgICAgIDwvTm9kZT4KICAgICAgICA8Tm9kZT4KICAgICAgICAgIDxOb2RlTmFtZT5EaWdpdGFs
+Q2VydGlmaWNhdGU8L05vZGVOYW1lPgogICAgICAgICAgPE5vZGU+CiAgICAgICAgICAgIDxOb2Rl
+TmFtZT5DZXJ0aWZpY2F0ZVR5cGU8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFsdWU+eDUwOXYz
+PC9WYWx1ZT4KICAgICAgICAgIDwvTm9kZT4KICAgICAgICAgIDxOb2RlPgogICAgICAgICAgICA8
+Tm9kZU5hbWU+Q2VydFNIQTI1NkZpbmdlcnByaW50PC9Ob2RlTmFtZT4KICAgICAgICAgICAgPFZh
+bHVlPjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYx
+ZjFmMWYxZjFmMWY8L1ZhbHVlPgogICAgICAgICAgPC9Ob2RlPgogICAgICAgIDwvTm9kZT4KICAg
+ICAgICA8Tm9kZT4KICAgICAgICAgIDxOb2RlTmFtZT5TSU08L05vZGVOYW1lPgogICAgICAgICAg
+PE5vZGU+CiAgICAgICAgICAgIDxOb2RlTmFtZT5JTVNJPC9Ob2RlTmFtZT4KICAgICAgICAgICAg
+PFZhbHVlPjEyMzQ1Nio8L1ZhbHVlPgogICAgICAgICAgPC9Ob2RlPgogICAgICAgICAgPE5vZGU+
+CiAgICAgICAgICAgIDxOb2RlTmFtZT5FQVBUeXBlPC9Ob2RlTmFtZT4KICAgICAgICAgICAgPFZh
+bHVlPjIzPC9WYWx1ZT4KICAgICAgICAgIDwvTm9kZT4KICAgICAgICA8L05vZGU+CiAgICAgIDwv
+Tm9kZT4KICAgIDwvTm9kZT4KICA8L05vZGU+CjwvTWdtdFRyZWU+
 
 --{boundary}
 Content-Type: application/x-x509-ca-cert
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithInvalidContentType.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithInvalidContentType.base64
index 906bfb3..2775a9f 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithInvalidContentType.base64
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithInvalidContentType.base64
@@ -1,85 +1,86 @@
-Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
-dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
-cHBsaWNhdGlvbi9wYXNzcG9pbnQtcHJvZmlsZQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBi
-YXNlNjQKClBFMW5iWFJVY21WbElIaHRiRzV6UFNKemVXNWpiV3c2Wkcxa1pHWXhMaklpUGdvZ0lE
-eFdaWEpFVkVRK01TNHlQQzlXWlhKRVZFUSsKQ2lBZ1BFNXZaR1UrQ2lBZ0lDQThUbTlrWlU1aGJX
-VStVR1Z5VUhKdmRtbGtaWEpUZFdKelkzSnBjSFJwYjI0OEwwNXZaR1ZPWVcxbApQZ29nSUNBZ1BG
-SlVVSEp2Y0dWeWRHbGxjejRLSUNBZ0lDQWdQRlI1Y0dVK0NpQWdJQ0FnSUNBZ1BFUkVSazVoYldV
-K2RYSnVPbmRtCllUcHRienBvYjNSemNHOTBNbVJ2ZERBdGNHVnljSEp2ZG1sa1pYSnpkV0p6WTNK
-cGNIUnBiMjQ2TVM0d1BDOUVSRVpPWVcxbFBnb2cKSUNBZ0lDQThMMVI1Y0dVK0NpQWdJQ0E4TDFK
-VVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQThUbTlrWlU1aApiV1UrYVRB
-d01Ud3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0
-WlQ1SWIyMWxVMUE4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0Fn
-SUNBZ1BFNXZaR1ZPWVcxbFBrWnlhV1Z1Wkd4NVRtRnQKWlR3dlRtOWtaVTVoYldVK0NpQWdJQ0Fn
-SUNBZ0lDQThWbUZzZFdVK1EyVnVkSFZ5ZVNCSWIzVnpaVHd2Vm1Gc2RXVStDaUFnSUNBZwpJQ0Fn
-UEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQ
-a1pSUkU0OEwwNXZaR1ZPCllXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbTFwTmk1amJ5NTFh
-end2Vm1Gc2RXVStDaUFnSUNBZ0lDQWdQQzlPYjJSbFBnb2cKSUNBZ0lDQWdJRHhPYjJSbFBnb2dJ
-Q0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbEp2WVcxcGJtZERiMjV6YjNKMGFYVnRUMGs4TDA1dgpa
-R1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBqRXhNakl6TXl3ME5EVTFOalk4TDFaaGJI
-VmxQZ29nSUNBZ0lDQWdJRHd2ClRtOWtaVDRLSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBOFRt
-OWtaVDRLSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrUTNKbFpHVnUKZEdsaGJEd3ZUbTlrWlU1aGJX
-VStDaUFnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStVbVZoYkcw
-OApMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbk5vWVd0bGJpNXpkR2x5Y21W
-a0xtTnZiVHd2Vm1Gc2RXVStDaUFnCklDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJS
-bFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbFZ6WlhKdVlXMWwKVUdGemMzZHZjbVE4TDA1
-dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9iMlJs
-VG1GdApaVDVWYzJWeWJtRnRaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gx
-WlQ1cVlXMWxjend2Vm1Gc2RXVStDaUFnCklDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0Fn
-SUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsQmgKYzNOM2IzSmtQQzlP
-YjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGxsdE9YVmFSRUYzVG5jOVBUd3ZW
-bUZzZFdVKwpDaUFnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pUNEtJ
-Q0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsClBrVkJVRTFsZEdodlpEd3ZUbTlrWlU1aGJXVStD
-aUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRa
-VDVGUVZCVWVYQmxQQzlPYjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdVK01q
-RThMMVpoYkhWbApQZ29nSUNBZ0lDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lE
-eE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJRHhPCmIyUmxUbUZ0WlQ1SmJtNWxjazFsZEdodlpE
-d3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGsxVExVTkkKUVZBdFZq
-SThMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4TDA1
-dlpHVStDaUFnSUNBZwpJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNB
-Z0lDQWdQRTV2WkdWT1lXMWxQa1JwWjJsMFlXeERaWEowCmFXWnBZMkYwWlR3dlRtOWtaVTVoYldV
-K0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtO
-bGNuUnBabWxqWVhSbFZIbHdaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gx
-WlQ1NE5UQTVkak04TDFaaApiSFZsUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0Fn
-SUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9iMlJsClRtRnRaVDVEWlhKMFUwaEJNalUy
-Um1sdVoyVnlVSEpwYm5ROEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4Vm1Gc2RXVSsK
-TVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1N
-V1l4WmpGbU1XWXhaakZtTVdZeApaakZtTVdZeFpqd3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ0lDQThM
-MDV2WkdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnCklEeE9iMlJsUGdvZ0lDQWdJ
-Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBsTkpUVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBOFRt
-OWsKWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQa2xOVTBrOEwwNXZaR1ZPWVcxbFBn
-b2dJQ0FnSUNBZ0lDQWdJQ0E4Vm1GcwpkV1UrYVcxemFUd3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ0lD
-QThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnCklDQWdJQ0FnUEU1dlpH
-Vk9ZVzFsUGtWQlVGUjVjR1U4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
-K01qUTgKTDFaaGJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHd2VG05
-a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnUEM5T2IyUmxQZ29nSUR3dlRtOWtaVDRLUEM5
-TloyMTBWSEpsWlQ0SwoKLS17Ym91bmRhcnl9CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24veC14
-NTA5LWNhLWNlcnQKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgpMUzB0TFMxQ1JV
-ZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VSTFJFTkRRV2hEWjBGM1NVSkJaMGxLUVVs
-TWJFWmtkM3BNClZuVnlUVUV3UjBOVGNVZFRTV0l6UkZGRlFrTjNWVUZOUWtsNFJVUkJUMEpuVGxZ
-S1FrRk5WRUl3VmtKVlEwSkVVVlJGZDBob1kwNU4KVkZsM1RWUkZlVTFVUlRGTlJFVXhWMmhqVGsx
-cVdYZE5WRUUxVFZSRk1VMUVSVEZYYWtGVFRWSkJkd3BFWjFsRVZsRlJSRVYzWkVaUgpWa0ZuVVRC
-RmVFMUpTVUpKYWtGT1FtZHJjV2hyYVVjNWR6QkNRVkZGUmtGQlQwTkJVVGhCVFVsSlFrTm5TME5C
-VVVWQkNucHVRVkJWCmVqSTJUWE5oWlRSM2N6UXpZM3BTTkRFdlNqSlJkSEpUU1ZwVlMyMVdWWE5X
-ZFcxRVlsbEljbEJPZGxSWVMxTk5XRUZqWlhkUFVrUlIKV1ZnS1VuRjJTSFp3YmpoRGMyTkNNU3R2
-UjFoYWRraDNlR28wZWxZd1YwdHZTeko2WlZocllYVXpkbU41YkROSVNVdDFjRXBtY1RKVQpSVUZE
-WldaV2Ftb3dkQXBLVnl0WU16VlFSMWR3T1M5SU5YcEpWVTVXVGxacVV6ZFZiWE00TkVsMlMyaFNR
-amcxTVRKUVFqbFZlVWhoCloxaFpWbGcxUjFkd1FXTldjSGxtY214U0NrWkpPVkZrYUdnclVHSnJN
-SFY1YTNSa1ltWXZRMlJtWjBoUGIyVmljbFIwZDFKc2FrMHcKYjBSMFdDc3lRM1kyYWpCM1FrczNh
-RVE0Y0ZCMlpqRXJkWGtLUjNwamVtbG5RVlV2TkV0M04yVmFjWGxrWmpsQ0t6VlNkWEJTSzBsYQph
-WEJZTkRGNFJXbEpja3RTZDNGcE5URTNWMWQ2V0dOcVlVY3lZMDVpWmpRMU1RcDRjRWcxVUc1V00y
-a3hkSEV3TkdwTlIxRlZla1ozClNVUkJVVUZDYnpSSFFVMUlOSGRJVVZsRVZsSXdUMEpDV1VWR1NY
-ZFlOSFp6T0VKcFFtTlRZMjlrQ2pWdWIxcElVazA0UlRRcmFVMUYKU1VkQk1WVmtTWGRSTjAxRWJV
-RkdTWGRZTkhaek9FSnBRbU5UWTI5a05XNXZXa2hTVFRoRk5DdHBiMUpoYTBaRVFWTUtUVkpCZDBS
-bgpXVVJXVVZGRVJYZGtSbEZXUVdkUk1FVjRaMmRyUVdkMVZWWXpSRTEwVnpaemQwUkJXVVJXVWpC
-VVFrRlZkMEYzUlVJdmVrRk1RbWRPClZncElVVGhGUWtGTlEwRlJXWGRFVVZsS1MyOWFTV2gyWTA1
-QlVVVk1RbEZCUkdkblJVSkJSbVpSY1U5VVFUZFNkamRMSzJ4MVVUZHcKYm1Gek5FSlpkMGhGQ2ps
-SFJWQXZkVzlvZGpaTFQza3dWRWRSUm1KeVVsUnFSbTlNVms1Q09VSmFNWGx0VFVSYU1DOVVTWGRK
-VldNMwpkMmszWVRoME5XMUZjVmxJTVRVemQxY0tZVmR2YjJsVGFubE1UR2gxU1RSelRuSk9RMDkw
-YVhOa1FuRXljakpOUmxoME5tZ3diVUZSCldVOVFkamhTT0VzM0wyWm5VM2hIUm5GNmFIbE9iVzFX
-VEFveGNVSktiR1I0TXpSVGNIZHpWRUZNVVZaUVlqUm9SM2RLZWxwbWNqRlEKWTNCRlVYZzJlRTF1
-Vkd3NGVFVlhXa1V6VFhNNU9YVmhWWGhpVVhGSmQxSjFDa3huUVU5clRrTnRXVEp0T0RsV2FIcGhT
-RW94ZFZZNApOVUZrVFM5MFJDdFpjMjFzYm01cWREbE1Va05sYW1KQ2FYQnFTVWRxVDFoeVp6RktV
-Q3RzZUZZS2JYVk5OSFpJSzFBdmJXeHRlSE5RClVIb3daRFkxWWl0RlIyMUtXbkJ2VEd0UEwzUmtU
-azUyUTFsNmFrcHdWRVZYY0VWelR6Wk9UV2hMV1c4OUNpMHRMUzB0UlU1RUlFTkYKVWxSSlJrbERR
-VlJGTFMwdExTMEsKLS17Ym91bmRhcnl9LS0K
+TUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5
+PXtib3VuZGFyeX07IGNoYXJzZXQ9VVRGLTgKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFz
+ZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9wYXNzcG9pbnQtcHJv
+ZmlsZTsgY2hhcnNldD1VVEYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKClBF
+MW5iWFJVY21WbElIaHRiRzV6UFNKemVXNWpiV3c2Wkcxa1pHWXhMaklpUGdvZ0lEeFdaWEpFVkVR
+K01TNHlQQzlXWlhKRVZFUSsKQ2lBZ1BFNXZaR1UrQ2lBZ0lDQThUbTlrWlU1aGJXVStVR1Z5VUhK
+dmRtbGtaWEpUZFdKelkzSnBjSFJwYjI0OEwwNXZaR1ZPWVcxbApQZ29nSUNBZ1BGSlVVSEp2Y0dW
+eWRHbGxjejRLSUNBZ0lDQWdQRlI1Y0dVK0NpQWdJQ0FnSUNBZ1BFUkVSazVoYldVK2RYSnVPbmRt
+CllUcHRienBvYjNSemNHOTBNbVJ2ZERBdGNHVnljSEp2ZG1sa1pYSnpkV0p6WTNKcGNIUnBiMjQ2
+TVM0d1BDOUVSRVpPWVcxbFBnb2cKSUNBZ0lDQThMMVI1Y0dVK0NpQWdJQ0E4TDFKVVVISnZjR1Z5
+ZEdsbGN6NEtJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQThUbTlrWlU1aApiV1UrYVRBd01Ud3ZUbTlr
+WlU1aGJXVStDaUFnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0WlQ1SWIyMWxV
+MUE4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZa
+R1ZPWVcxbFBrWnlhV1Z1Wkd4NVRtRnQKWlR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQThW
+bUZzZFdVK1JYaGhiWEJzWlNCT1pYUjNiM0pyUEM5V1lXeDFaVDRLSUNBZwpJQ0FnSUNBOEwwNXZa
+R1UrQ2lBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrUmxGRVRq
+d3ZUbTlrClpVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrYUc5MGMzQnZkQzVsZUdGdGNH
+eGxMbTVsZER3dlZtRnNkV1UrQ2lBZ0lDQWcKSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUR4T2Iy
+UmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxKdllXMXBibWREYjI1egpiM0owYVhWdFQw
+azhMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQakV4TWpJek15dzBORFUxTmpZ
+OEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNB
+Z0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBOFRtOWsKWlU1aGJXVStRM0psWkdWdWRHbGhiRHd2VG05
+a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05awpaVTVoYldV
+K1VtVmhiRzA4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUG1WNFlXMXdiR1V1
+WTI5dFBDOVdZV3gxClpUNEtJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ1BFNXZaR1Ur
+Q2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1ZYTmwKY201aGJXVlFZWE56ZDI5eVpEd3ZUbTlr
+WlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dgpaR1ZP
+WVcxbFBsVnpaWEp1WVcxbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQ
+blZ6WlhJOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdQ
+RTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFRtRnQKWlQ1UVlYTnpkMjl5WkR3dlRtOWta
+VTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhXWVd4MVpUNWpSMFo2WXpOa2RtTnRVVDA4TDFaaApi
+SFZsUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lD
+QWdJQ0FnSUNBZ0lEeE9iMlJsClRtRnRaVDVGUVZCTlpYUm9iMlE4TDA1dlpHVk9ZVzFsUGdvZ0lD
+QWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWcKSUNBOFRtOWtaVTVoYldVK1JV
+RlFWSGx3WlR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQakl4UEM5
+VwpZV3gxWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4VG05
+a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnCklDQThUbTlrWlU1aGJXVStTVzV1WlhKTlpYUm9iMlE4TDA1
+dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJRHhXWVd4MVpUNU4KVXkxRFNFRlFMVll5UEM5
+V1lXeDFaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJs
+UGdvZwpJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0Fn
+SUR4T2IyUmxUbUZ0WlQ1RWFXZHBkR0ZzClEyVnlkR2xtYVdOaGRHVThMMDV2WkdWT1lXMWxQZ29n
+SUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEow
+YVdacFkyRjBaVlI1Y0dVOEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4Vm1Gc2RXVStl
+RFV3T1hZegpQQzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUNBZ0lDQWdJ
+RHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4ClRtOWtaVTVoYldVK1EyVnlkRk5JUVRJMU5rWnBi
+bWRsY25CeWFXNTBQQzlPYjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BGWmgKYkhWbFBqRm1N
+V1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1X
+WXhaakZtTVdZeApaakZtTVdZeFpqRm1NV1k4TDFaaGJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2Iy
+UmxQZ29nSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnCklDQWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lD
+QWdJRHhPYjJSbFRtRnRaVDVUU1UwOEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWcKUEU1dlpH
+VStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0WlQ1SlRWTkpQQzlPYjJSbFRtRnRaVDRLSUNB
+Z0lDQWdJQ0FnSUNBZwpQRlpoYkhWbFBqRXlNelExTmlvOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNB
+Z1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1UrCkNpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJS
+bFRtRnRaVDVGUVZCVWVYQmxQQzlPYjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BGWmgKYkhW
+bFBqSXpQQzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUNBZ0lDQThMMDV2
+WkdVK0NpQWdJQ0FnSUR3dgpUbTlrWlQ0S0lDQWdJRHd2VG05a1pUNEtJQ0E4TDA1dlpHVStDand2
+VFdkdGRGUnlaV1UrCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXg1
+MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFDUlVk
+SlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtRVWxN
+YkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5UbFlL
+UWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpUazFx
+V1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5VVEJG
+ZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMwTkJV
+VVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZYTldk
+VzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01TdHZS
+MWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJVRkRa
+V1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJoU1Fq
+ZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdKck1I
+VjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtzM2FF
+UTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxhCmFY
+QllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVXTTJr
+eGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZHU1hk
+WU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFFYlVG
+R1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJkMFJu
+CldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldVakJV
+UWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZMDVC
+VVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZDamxI
+UlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNYZEpW
+V00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1EwOTBh
+WE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JXMVdU
+QW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVFMXVW
+R3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhwaFNF
+b3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpGS1VD
+dHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNSa1Rr
+NTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmtsRFFW
+UkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
\ No newline at end of file
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithMissingBoundary.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithMissingBoundary.base64
index 3fa97d1..7023453 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithMissingBoundary.base64
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithMissingBoundary.base64
@@ -1,85 +1,86 @@
-Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
-dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
-cHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6
-IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29n
-SUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVo
-YldVK1VHVnlVSEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0Fn
-UEZKVVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhi
-V1UrZFhKdU9uZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZ
-M0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThM
-MUpVVUhKdmNHVnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSth
-VEF3TVR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRt
-RnRaVDVJYjIxbFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
-QWdJQ0FnSUNBOFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklD
-QWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcx
-bFBrWlJSRTQ4TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1
-MWF6d3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdv
-Z0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2
-ClpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpo
-YkhWbFBnb2dJQ0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4
-VG05a1pUNEtJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVo
-YldVK0NpQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhi
-RzA4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHlj
-bVZrTG1OdmJUd3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9i
-MlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThM
-MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2Iy
-UmxUbUZ0ClpUNVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDVxWVcxbGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lD
-QWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BD
-OU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3
-dlZtRnNkV1UrCkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0
-S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldV
-K0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1G
-dFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1Ur
-TWpFOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0Fn
-SUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2
-WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0
-VmpJOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThM
-MDV2WkdVK0NpQWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJ
-Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhi
-V1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQ
-a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
-VTJSbWx1WjJWeVVISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
-KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
-bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
-OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
-Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4
-VG05awpaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFs
-UGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0Fn
-SUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2
-WkdWT1lXMWxQa1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNk
-V1UrTWpROApMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZU
-bTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQ
-QzlOWjIxMFZISmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94
-LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFD
-UlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtR
-VWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5U
-bFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpU
-azFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5V
-VEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMw
-TkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZY
-TldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01T
-dHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJV
-RkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJo
-U1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdK
-ck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtz
-M2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxh
-CmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVX
-TTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZH
-U1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFF
-YlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJk
-MFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldV
-akJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZ
-MDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZD
-amxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNY
-ZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1Ew
-OTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JX
-MVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVF
-MXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhw
-aFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpG
-S1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNS
-a1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmts
-RFFWUkZMUzB0TFMwSwo=
+TUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5
+PXtib3VuZGFyeX07IGNoYXJzZXQ9VVRGLTgKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFz
+ZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXBhc3Nwb2ludC1w
+cm9maWxlOyBjaGFyc2V0PVVURi04CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NAoK
+UEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29nSUR4V1pYSkVW
+RVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVoYldVK1VHVnlV
+SEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0FnUEZKVVVISnZj
+R1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhiV1UrZFhKdU9u
+ZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZM0pwY0hScGIy
+NDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThMMUpVVUhKdmNH
+VnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSthVEF3TVR3dlRt
+OWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRtRnRaVDVJYjIx
+bFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1
+dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNB
+OFZtRnNkV1UrUlhoaGJYQnNaU0JPWlhSM2IzSnJQQzlXWVd4MVpUNEtJQ0FnCklDQWdJQ0E4TDA1
+dlpHVStDaUFnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStSbEZF
+VGp3dlRtOWsKWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4Vm1Gc2RXVSthRzkwYzNCdmRDNWxlR0Z0
+Y0d4bExtNWxkRHd2Vm1Gc2RXVStDaUFnSUNBZwpJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhP
+YjJSbFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbEp2WVcxcGJtZERiMjV6CmIzSjBhWFZ0
+VDBrOEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBqRXhNakl6TXl3ME5EVTFO
+alk4TDFaaGJIVmwKUGdvZ0lDQWdJQ0FnSUR3dlRtOWtaVDRLSUNBZ0lDQWdQQzlPYjJSbFBnb2dJ
+Q0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0E4VG05awpaVTVoYldVK1EzSmxaR1Z1ZEdsaGJEd3ZU
+bTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrClpVNWhi
+V1UrVW1WaGJHMDhMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbVY0WVcxd2JH
+VXVZMjl0UEM5V1lXeDEKWlQ0S0lDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEU1dlpH
+VStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrVlhObApjbTVoYldWUVlYTnpkMjl5WkR3dlRt
+OWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2ClpH
+Vk9ZVzFsUGxWelpYSnVZVzFsUEM5T2IyUmxUbUZ0WlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRlpoYkhW
+bFBuVnpaWEk4TDFaaGJIVmwKUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNB
+Z1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9iMlJsVG1GdApaVDVRWVhOemQyOXlaRHd2VG05
+a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gxWlQ1alIwWjZZek5rZG1OdFVUMDhMMVpo
+CmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFn
+SUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNUZRVkJOWlhSb2IyUThMMDV2WkdWT1lXMWxQZ29n
+SUNBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZwpJQ0E4VG05a1pVNWhiV1Ur
+UlVGUVZIbHdaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBqSXhQ
+QzlXCllXeDFaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThU
+bTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWcKSUNBOFRtOWtaVTVoYldVK1NXNXVaWEpOWlhSb2IyUThM
+MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gxWlQ1TgpVeTFEU0VGUUxWWXlQ
+QzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2Iy
+UmxQZ29nCklDQWdJQ0FnSUR3dlRtOWtaVDRLSUNBZ0lDQWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lD
+QWdJRHhPYjJSbFRtRnRaVDVFYVdkcGRHRnMKUTJWeWRHbG1hV05oZEdVOEwwNXZaR1ZPWVcxbFBn
+b2dJQ0FnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbApUbUZ0WlQ1RFpY
+SjBhV1pwWTJGMFpWUjVjR1U4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
+K2VEVXdPWFl6ClBDOVdZV3gxWlQ0S0lDQWdJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNB
+Z0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ0lDQTgKVG05a1pVNWhiV1UrUTJWeWRGTklRVEkxTmta
+cGJtZGxjbkJ5YVc1MFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaApiSFZsUGpG
+bU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZt
+TVdZeFpqRm1NV1l4ClpqRm1NV1l4WmpGbU1XWThMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlP
+YjJSbFBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWcKSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0Fn
+SUNBZ0lEeE9iMlJsVG1GdFpUNVRTVTA4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZwpQRTV2
+WkdVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFRtRnRaVDVKVFZOSlBDOU9iMlJsVG1GdFpUNEtJ
+Q0FnSUNBZ0lDQWdJQ0FnClBGWmhiSFZsUGpFeU16UTFOaW84TDFaaGJIVmxQZ29nSUNBZ0lDQWdJ
+Q0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVSsKQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9i
+MlJsVG1GdFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaApi
+SFZsUGpJelBDOVdZV3gxWlQ0S0lDQWdJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNBOEww
+NXZaR1UrQ2lBZ0lDQWdJRHd2ClRtOWtaVDRLSUNBZ0lEd3ZUbTlrWlQ0S0lDQThMMDV2WkdVK0Nq
+d3ZUV2R0ZEZSeVpXVSsKCi0te2JvdW5kYXJ5fQpDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL3gt
+eDUwOS1jYS1jZXJ0CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NAoKTFMwdExTMUNS
+VWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVUkxSRU5EUVdoRFowRjNTVUpCWjBsS1FV
+bE1iRVprZDNwTQpWblZ5VFVFd1IwTlRjVWRUU1dJelJGRkZRa04zVlVGTlFrbDRSVVJCVDBKblRs
+WUtRa0ZOVkVJd1ZrSlZRMEpFVVZSRmQwaG9ZMDVOClZGbDNUVlJGZVUxVVJURk5SRVV4VjJoalRr
+MXFXWGROVkVFMVRWUkZNVTFFUlRGWGFrRlRUVkpCZHdwRVoxbEVWbEZSUkVWM1pFWlIKVmtGblVU
+QkZlRTFKU1VKSmFrRk9RbWRyY1docmFVYzVkekJDUVZGRlJrRkJUME5CVVRoQlRVbEpRa05uUzBO
+QlVVVkJDbnB1UVZCVgplakkyVFhOaFpUUjNjelF6WTNwU05ERXZTakpSZEhKVFNWcFZTMjFXVlhO
+V2RXMUVZbGxJY2xCT2RsUllTMU5OV0VGalpYZFBVa1JSCldWZ0tVbkYyU0had2JqaERjMk5DTVN0
+dlIxaGFka2gzZUdvMGVsWXdWMHR2U3pKNlpWaHJZWFV6ZG1ONWJETklTVXQxY0VwbWNUSlUKUlVG
+RFpXWldhbW93ZEFwS1Z5dFlNelZRUjFkd09TOUlOWHBKVlU1V1RsWnFVemRWYlhNNE5FbDJTMmhT
+UWpnMU1USlFRamxWZVVoaApaMWhaVmxnMVIxZHdRV05XY0hsbWNteFNDa1pKT1ZGa2FHZ3JVR0py
+TUhWNWEzUmtZbVl2UTJSbVowaFBiMlZpY2xSMGQxSnNhazB3CmIwUjBXQ3N5UTNZMmFqQjNRa3Mz
+YUVRNGNGQjJaakVyZFhrS1IzcGplbWxuUVZVdk5FdDNOMlZhY1hsa1pqbENLelZTZFhCU0swbGEK
+YVhCWU5ERjRSV2xKY2t0U2QzRnBOVEUzVjFkNldHTnFZVWN5WTA1aVpqUTFNUXA0Y0VnMVVHNVdN
+Mmt4ZEhFd05HcE5SMUZWZWtaMwpTVVJCVVVGQ2J6UkhRVTFJTkhkSVVWbEVWbEl3VDBKQ1dVVkdT
+WGRZTkhaek9FSnBRbU5UWTI5a0NqVnViMXBJVWswNFJUUXJhVTFGClNVZEJNVlZrU1hkUk4wMUVi
+VUZHU1hkWU5IWnpPRUpwUW1OVFkyOWtOVzV2V2toU1RUaEZOQ3RwYjFKaGEwWkVRVk1LVFZKQmQw
+Um4KV1VSV1VWRkVSWGRrUmxGV1FXZFJNRVY0WjJkclFXZDFWVll6UkUxMFZ6WnpkMFJCV1VSV1Vq
+QlVRa0ZWZDBGM1JVSXZla0ZNUW1kTwpWZ3BJVVRoRlFrRk5RMEZSV1hkRVVWbEtTMjlhU1doMlkw
+NUJVVVZNUWxGQlJHZG5SVUpCUm1aUmNVOVVRVGRTZGpkTEsyeDFVVGR3CmJtRnpORUpaZDBoRkNq
+bEhSVkF2ZFc5b2RqWkxUM2t3VkVkUlJtSnlVbFJxUm05TVZrNUNPVUphTVhsdFRVUmFNQzlVU1hk
+SlZXTTMKZDJrM1lUaDBOVzFGY1ZsSU1UVXpkMWNLWVZkdmIybFRhbmxNVEdoMVNUUnpUbkpPUTA5
+MGFYTmtRbkV5Y2pKTlJsaDBObWd3YlVGUgpXVTlRZGpoU09FczNMMlpuVTNoSFJuRjZhSGxPYlcx
+V1RBb3hjVUpLYkdSNE16UlRjSGR6VkVGTVVWWlFZalJvUjNkS2VscG1jakZRClkzQkZVWGcyZUUx
+dVZHdzRlRVZYV2tVelRYTTVPWFZoVlhoaVVYRkpkMUoxQ2t4blFVOXJUa050V1RKdE9EbFdhSHBo
+U0VveGRWWTQKTlVGa1RTOTBSQ3RaYzIxc2JtNXFkRGxNVWtObGFtSkNhWEJxU1VkcVQxaHlaekZL
+VUN0c2VGWUtiWFZOTkhaSUsxQXZiV3h0ZUhOUQpVSG93WkRZMVlpdEZSMjFLV25CdlRHdFBMM1Jr
+VGs1MlExbDZha3B3VkVWWGNFVnpUelpPVFdoTFdXODlDaTB0TFMwdFJVNUVJRU5GClVsUkpSa2xE
+UVZSRkxTMHRMUzBLCg==
\ No newline at end of file
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithNonBase64Part.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithNonBase64Part.base64
index 975f8e5..5c23f61 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithNonBase64Part.base64
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithNonBase64Part.base64
@@ -1,85 +1,86 @@
-Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
-dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTMyCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
-cHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6
-IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29n
-SUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVo
-YldVK1VHVnlVSEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0Fn
-UEZKVVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhi
-V1UrZFhKdU9uZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZ
-M0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThM
-MUpVVUhKdmNHVnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSth
-VEF3TVR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRt
-RnRaVDVJYjIxbFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
-QWdJQ0FnSUNBOFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklD
-QWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcx
-bFBrWlJSRTQ4TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1
-MWF6d3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdv
-Z0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2
-ClpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpo
-YkhWbFBnb2dJQ0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4
-VG05a1pUNEtJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVo
-YldVK0NpQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhi
-RzA4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHlj
-bVZrTG1OdmJUd3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9i
-MlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThM
-MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2Iy
-UmxUbUZ0ClpUNVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDVxWVcxbGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lD
-QWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BD
-OU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3
-dlZtRnNkV1UrCkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0
-S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldV
-K0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1G
-dFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1Ur
-TWpFOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0Fn
-SUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2
-WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0
-VmpJOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThM
-MDV2WkdVK0NpQWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJ
-Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhi
-V1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQ
-a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
-VTJSbWx1WjJWeVVISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
-KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
-bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
-OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
-Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4
-VG05awpaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFs
-UGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0Fn
-SUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2
-WkdWT1lXMWxQa1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNk
-V1UrTWpROApMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZU
-bTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQ
-QzlOWjIxMFZISmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94
-LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFD
-UlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtR
-VWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5U
-bFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpU
-azFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5V
-VEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMw
-TkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZY
-TldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01T
-dHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJV
-RkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJo
-U1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdK
-ck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtz
-M2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxh
-CmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVX
-TTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZH
-U1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFF
-YlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJk
-MFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldV
-akJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZ
-MDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZD
-amxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNY
-ZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1Ew
-OTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JX
-MVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVF
-MXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhw
-aFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpG
-S1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNS
-a1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmts
-RFFWUkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
+TUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5
+PXtib3VuZGFyeX07IGNoYXJzZXQ9VVRGLTgKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogOGJp
+dAoKLS17Ym91bmRhcnl9CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24veC1wYXNzcG9pbnQtcHJv
+ZmlsZTsgY2hhcnNldD1VVEYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKClBF
+MW5iWFJVY21WbElIaHRiRzV6UFNKemVXNWpiV3c2Wkcxa1pHWXhMaklpUGdvZ0lEeFdaWEpFVkVR
+K01TNHlQQzlXWlhKRVZFUSsKQ2lBZ1BFNXZaR1UrQ2lBZ0lDQThUbTlrWlU1aGJXVStVR1Z5VUhK
+dmRtbGtaWEpUZFdKelkzSnBjSFJwYjI0OEwwNXZaR1ZPWVcxbApQZ29nSUNBZ1BGSlVVSEp2Y0dW
+eWRHbGxjejRLSUNBZ0lDQWdQRlI1Y0dVK0NpQWdJQ0FnSUNBZ1BFUkVSazVoYldVK2RYSnVPbmRt
+CllUcHRienBvYjNSemNHOTBNbVJ2ZERBdGNHVnljSEp2ZG1sa1pYSnpkV0p6WTNKcGNIUnBiMjQ2
+TVM0d1BDOUVSRVpPWVcxbFBnb2cKSUNBZ0lDQThMMVI1Y0dVK0NpQWdJQ0E4TDFKVVVISnZjR1Z5
+ZEdsbGN6NEtJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQThUbTlrWlU1aApiV1UrYVRBd01Ud3ZUbTlr
+WlU1aGJXVStDaUFnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0WlQ1SWIyMWxV
+MUE4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZa
+R1ZPWVcxbFBrWnlhV1Z1Wkd4NVRtRnQKWlR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQThW
+bUZzZFdVK1JYaGhiWEJzWlNCT1pYUjNiM0pyUEM5V1lXeDFaVDRLSUNBZwpJQ0FnSUNBOEwwNXZa
+R1UrQ2lBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrUmxGRVRq
+d3ZUbTlrClpVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrYUc5MGMzQnZkQzVsZUdGdGNH
+eGxMbTVsZER3dlZtRnNkV1UrQ2lBZ0lDQWcKSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUR4T2Iy
+UmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxKdllXMXBibWREYjI1egpiM0owYVhWdFQw
+azhMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQakV4TWpJek15dzBORFUxTmpZ
+OEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNB
+Z0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBOFRtOWsKWlU1aGJXVStRM0psWkdWdWRHbGhiRHd2VG05
+a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05awpaVTVoYldV
+K1VtVmhiRzA4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUG1WNFlXMXdiR1V1
+WTI5dFBDOVdZV3gxClpUNEtJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ1BFNXZaR1Ur
+Q2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1ZYTmwKY201aGJXVlFZWE56ZDI5eVpEd3ZUbTlr
+WlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dgpaR1ZP
+WVcxbFBsVnpaWEp1WVcxbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQ
+blZ6WlhJOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdQ
+RTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFRtRnQKWlQ1UVlYTnpkMjl5WkR3dlRtOWta
+VTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhXWVd4MVpUNWpSMFo2WXpOa2RtTnRVVDA4TDFaaApi
+SFZsUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lD
+QWdJQ0FnSUNBZ0lEeE9iMlJsClRtRnRaVDVGUVZCTlpYUm9iMlE4TDA1dlpHVk9ZVzFsUGdvZ0lD
+QWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWcKSUNBOFRtOWtaVTVoYldVK1JV
+RlFWSGx3WlR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQakl4UEM5
+VwpZV3gxWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4VG05
+a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnCklDQThUbTlrWlU1aGJXVStTVzV1WlhKTlpYUm9iMlE4TDA1
+dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJRHhXWVd4MVpUNU4KVXkxRFNFRlFMVll5UEM5
+V1lXeDFaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJs
+UGdvZwpJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0Fn
+SUR4T2IyUmxUbUZ0WlQ1RWFXZHBkR0ZzClEyVnlkR2xtYVdOaGRHVThMMDV2WkdWT1lXMWxQZ29n
+SUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEow
+YVdacFkyRjBaVlI1Y0dVOEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4Vm1Gc2RXVStl
+RFV3T1hZegpQQzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUNBZ0lDQWdJ
+RHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4ClRtOWtaVTVoYldVK1EyVnlkRk5JUVRJMU5rWnBi
+bWRsY25CeWFXNTBQQzlPYjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BGWmgKYkhWbFBqRm1N
+V1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1X
+WXhaakZtTVdZeApaakZtTVdZeFpqRm1NV1k4TDFaaGJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2Iy
+UmxQZ29nSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnCklDQWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lD
+QWdJRHhPYjJSbFRtRnRaVDVUU1UwOEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWcKUEU1dlpH
+VStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0WlQ1SlRWTkpQQzlPYjJSbFRtRnRaVDRLSUNB
+Z0lDQWdJQ0FnSUNBZwpQRlpoYkhWbFBqRXlNelExTmlvOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNB
+Z1BDOU9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1UrCkNpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJS
+bFRtRnRaVDVGUVZCVWVYQmxQQzlPYjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BGWmgKYkhW
+bFBqSXpQQzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUNBZ0lDQThMMDV2
+WkdVK0NpQWdJQ0FnSUR3dgpUbTlrWlQ0S0lDQWdJRHd2VG05a1pUNEtJQ0E4TDA1dlpHVStDand2
+VFdkdGRGUnlaV1UrCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXg1
+MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFDUlVk
+SlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtRVWxN
+YkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5UbFlL
+UWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpUazFx
+V1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5VVEJG
+ZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMwTkJV
+VVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZYTldk
+VzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01TdHZS
+MWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJVRkRa
+V1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJoU1Fq
+ZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdKck1I
+VjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtzM2FF
+UTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxhCmFY
+QllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVXTTJr
+eGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZHU1hk
+WU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFFYlVG
+R1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJkMFJu
+CldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldVakJV
+UWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZMDVC
+VVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZDamxI
+UlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNYZEpW
+V00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1EwOTBh
+WE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JXMVdU
+QW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVFMXVW
+R3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhwaFNF
+b3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpGS1VD
+dHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNSa1Rr
+NTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmtsRFFW
+UkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
\ No newline at end of file
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithUpdateIdentifier.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithUpdateIdentifier.base64
new file mode 100644
index 0000000..bab7607
--- /dev/null
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithUpdateIdentifier.base64
@@ -0,0 +1,88 @@
+TUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5
+PXtib3VuZGFyeX07IGNoYXJzZXQ9VVRGLTgKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFz
+ZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXBhc3Nwb2ludC1w
+cm9maWxlOyBjaGFyc2V0PVVURi04CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NAoK
+UEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29nSUR4V1pYSkVW
+RVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVoYldVK1VHVnlV
+SEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0FnUEZKVVVISnZj
+R1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhiV1UrZFhKdU9u
+ZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZM0pwY0hScGIy
+NDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThMMUpVVUhKdmNH
+VnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVStWWEJrWVhSbFNX
+UmxiblJwWm1sbGNqd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lEeFdZV3gxWlQ0eE1qTTBQQzlXWVd4
+MVpUNEsKSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoYldV
+K2FUQXdNVHd2VG05a1pVNWhiV1UrQ2lBZwpJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJS
+bFRtRnRaVDVJYjIxbFUxQThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJRHhPCmIyUmxQZ29nSUNB
+Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdFpUd3ZUbTlrWlU1aGJXVStDaUFn
+SUNBZ0lDQWcKSUNBOFZtRnNkV1UrUlhoaGJYQnNaU0JPWlhSM2IzSnJQQzlXWVd4MVpUNEtJQ0Fn
+SUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZwpQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlr
+WlU1aGJXVStSbEZFVGp3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthRzkw
+YzNCdmRDNWxlR0Z0Y0d4bExtNWxkRHd2Vm1Gc2RXVStDaUFnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJ
+Q0FnSUNBZ0lEeE8KYjJSbFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbEp2WVcxcGJtZERi
+MjV6YjNKMGFYVnRUMGs4TDA1dlpHVk9ZVzFsUGdvZwpJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBqRXhN
+akl6TXl3ME5EVTFOalk4TDFaaGJIVmxQZ29nSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnCklDQWdQ
+QzlPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrUTNKbFpH
+VnVkR2xoYkR3dlRtOWsKWlU1aGJXVStDaUFnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lD
+QThUbTlrWlU1aGJXVStVbVZoYkcwOEwwNXZaR1ZPWVcxbApQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJI
+VmxQbVY0WVcxd2JHVXVZMjl0UEM5V1lXeDFaVDRLSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnCklD
+QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrVlhObGNtNWhiV1ZRWVhO
+emQyOXlaRHd2VG05a1pVNWgKYldVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNB
+Z0lDQWdQRTV2WkdWT1lXMWxQbFZ6WlhKdVlXMWxQQzlPYjJSbApUbUZ0WlQ0S0lDQWdJQ0FnSUNB
+Z0lDQWdQRlpoYkhWbFBuVnpaWEk4TDFaaGJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29n
+CklDQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9iMlJsVG1GdFpUNVFZWE56
+ZDI5eVpEd3ZUbTlrWlU1aGJXVSsKQ2lBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gxWlQ1alIwWjZZek5r
+ZG1OdFVUMDhMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbApQZ29nSUNBZ0lDQWdJQ0Fn
+UEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0WlQ1RlFWQk5aWFJvYjJROEwwNXZa
+R1ZPCllXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQThU
+bTlrWlU1aGJXVStSVUZRVkhsd1pUd3YKVG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lDQWdQ
+RlpoYkhWbFBqSXhQQzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEM5TwpiMlJsUGdvZ0lDQWdJ
+Q0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrU1c1dVpY
+Sk5aWFJvCmIyUThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gxWlQ1TlV5
+MURTRUZRTFZZeVBDOVdZV3gxWlQ0S0lDQWcKSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
+QWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUNBZwpJQ0E4VG05a1pU
+NEtJQ0FnSUNBZ0lDQWdJRHhPYjJSbFRtRnRaVDVFYVdkcGRHRnNRMlZ5ZEdsbWFXTmhkR1U4TDA1
+dlpHVk9ZVzFsClBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJS
+bFRtRnRaVDVEWlhKMGFXWnBZMkYwWlZSNWNHVTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNB
+Z0lDQThWbUZzZFdVK2VEVXdPWFl6UEM5V1lXeDFaVDRLSUNBZ0lDQWdJQ0FnSUR3dgpUbTlrWlQ0
+S0lDQWdJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRMlZ5
+ZEZOSVFUSTFOa1pwCmJtZGxjbkJ5YVc1MFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0Fn
+UEZaaGJIVmxQakZtTVdZeFpqRm1NV1l4WmpGbU1XWXgKWmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4
+WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZOEwxWmhiSFZsUGdvZwpJQ0Fn
+SUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNBOFRtOWta
+VDRLSUNBZ0lDQWdJQ0FnCklEeE9iMlJsVG1GdFpUNVRTVTA4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJ
+Q0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKVFZOSlBDOU9i
+MlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQakV5TXpRMU5pbzhMMVpoYkhWbApQ
+Z29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lD
+QWdJQ0FnSUR4T2IyUmxUbUZ0ClpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lD
+QWdJQ0FnUEZaaGJIVmxQakl6UEM5V1lXeDFaVDRLSUNBZ0lDQWcKSUNBZ0lEd3ZUbTlrWlQ0S0lD
+QWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUR3dlRtOWtaVDRLSUNB
+OApMMDV2WkdVK0Nqd3ZUV2R0ZEZSeVpXVSsKCi0te2JvdW5kYXJ5fQpDb250ZW50LVR5cGU6IGFw
+cGxpY2F0aW9uL3gteDUwOS1jYS1jZXJ0CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2
+NAoKTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVUkxSRU5EUVdoRFow
+RjNTVUpCWjBsS1FVbE1iRVprZDNwTQpWblZ5VFVFd1IwTlRjVWRUU1dJelJGRkZRa04zVlVGTlFr
+bDRSVVJCVDBKblRsWUtRa0ZOVkVJd1ZrSlZRMEpFVVZSRmQwaG9ZMDVOClZGbDNUVlJGZVUxVVJU
+Rk5SRVV4VjJoalRrMXFXWGROVkVFMVRWUkZNVTFFUlRGWGFrRlRUVkpCZHdwRVoxbEVWbEZSUkVW
+M1pFWlIKVmtGblVUQkZlRTFKU1VKSmFrRk9RbWRyY1docmFVYzVkekJDUVZGRlJrRkJUME5CVVRo
+QlRVbEpRa05uUzBOQlVVVkJDbnB1UVZCVgplakkyVFhOaFpUUjNjelF6WTNwU05ERXZTakpSZEhK
+VFNWcFZTMjFXVlhOV2RXMUVZbGxJY2xCT2RsUllTMU5OV0VGalpYZFBVa1JSCldWZ0tVbkYyU0ha
+d2JqaERjMk5DTVN0dlIxaGFka2gzZUdvMGVsWXdWMHR2U3pKNlpWaHJZWFV6ZG1ONWJETklTVXQx
+Y0VwbWNUSlUKUlVGRFpXWldhbW93ZEFwS1Z5dFlNelZRUjFkd09TOUlOWHBKVlU1V1RsWnFVemRW
+YlhNNE5FbDJTMmhTUWpnMU1USlFRamxWZVVoaApaMWhaVmxnMVIxZHdRV05XY0hsbWNteFNDa1pK
+T1ZGa2FHZ3JVR0pyTUhWNWEzUmtZbVl2UTJSbVowaFBiMlZpY2xSMGQxSnNhazB3CmIwUjBXQ3N5
+UTNZMmFqQjNRa3MzYUVRNGNGQjJaakVyZFhrS1IzcGplbWxuUVZVdk5FdDNOMlZhY1hsa1pqbENL
+elZTZFhCU0swbGEKYVhCWU5ERjRSV2xKY2t0U2QzRnBOVEUzVjFkNldHTnFZVWN5WTA1aVpqUTFN
+UXA0Y0VnMVVHNVdNMmt4ZEhFd05HcE5SMUZWZWtaMwpTVVJCVVVGQ2J6UkhRVTFJTkhkSVVWbEVW
+bEl3VDBKQ1dVVkdTWGRZTkhaek9FSnBRbU5UWTI5a0NqVnViMXBJVWswNFJUUXJhVTFGClNVZEJN
+VlZrU1hkUk4wMUViVUZHU1hkWU5IWnpPRUpwUW1OVFkyOWtOVzV2V2toU1RUaEZOQ3RwYjFKaGEw
+WkVRVk1LVFZKQmQwUm4KV1VSV1VWRkVSWGRrUmxGV1FXZFJNRVY0WjJkclFXZDFWVll6UkUxMFZ6
+WnpkMFJCV1VSV1VqQlVRa0ZWZDBGM1JVSXZla0ZNUW1kTwpWZ3BJVVRoRlFrRk5RMEZSV1hkRVVW
+bEtTMjlhU1doMlkwNUJVVVZNUWxGQlJHZG5SVUpCUm1aUmNVOVVRVGRTZGpkTEsyeDFVVGR3CmJt
+RnpORUpaZDBoRkNqbEhSVkF2ZFc5b2RqWkxUM2t3VkVkUlJtSnlVbFJxUm05TVZrNUNPVUphTVhs
+dFRVUmFNQzlVU1hkSlZXTTMKZDJrM1lUaDBOVzFGY1ZsSU1UVXpkMWNLWVZkdmIybFRhbmxNVEdo
+MVNUUnpUbkpPUTA5MGFYTmtRbkV5Y2pKTlJsaDBObWd3YlVGUgpXVTlRZGpoU09FczNMMlpuVTNo
+SFJuRjZhSGxPYlcxV1RBb3hjVUpLYkdSNE16UlRjSGR6VkVGTVVWWlFZalJvUjNkS2VscG1jakZR
+ClkzQkZVWGcyZUUxdVZHdzRlRVZYV2tVelRYTTVPWFZoVlhoaVVYRkpkMUoxQ2t4blFVOXJUa050
+V1RKdE9EbFdhSHBoU0VveGRWWTQKTlVGa1RTOTBSQ3RaYzIxc2JtNXFkRGxNVWtObGFtSkNhWEJx
+U1VkcVQxaHlaekZLVUN0c2VGWUtiWFZOTkhaSUsxQXZiV3h0ZUhOUQpVSG93WkRZMVlpdEZSMjFL
+V25CdlRHdFBMM1JrVGs1MlExbDZha3B3VkVWWGNFVnpUelpPVFdoTFdXODlDaTB0TFMwdFJVNUVJ
+RU5GClVsUkpSa2xEUVZSRkxTMHRMUzBLCi0te2JvdW5kYXJ5fS0tCg==
\ No newline at end of file
diff --git a/wifi/tests/assets/hsr1/README.txt b/wifi/tests/assets/hsr1/README.txt
index d1f8384..9f3cdc2 100644
--- a/wifi/tests/assets/hsr1/README.txt
+++ b/wifi/tests/assets/hsr1/README.txt
@@ -2,4 +2,5 @@
 HSR1ProfileWithCACert.base64 - base64 encoded of the data contained in HSR1ProfileWithCAWith.conf
 HSR1ProfileWithNonBase64Part.base64 - base64 encoded installation file that contains a part of non-base64 encoding type
 HSR1ProfileWithMissingBoundary.base64 - base64 encoded installation file with missing end-boundary in the MIME data
-HSR1ProfileWithInvalidContentType.base64 - base64 encoded installation file with that contains a MIME part with an invalid content type.
+HSR1ProfileWithInvalidContentType.base64 - base64 encoded installation file with that contains a MIME part with an invalid content type
+HSR1ProfileWithUpdateIdentifier.base64 - base64 encoded installation file with that contains an R2 update identifier
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index 0ce5d66..ea08ea8 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -38,6 +38,7 @@
     private static final String TEST_PACKAGE_NAME = "com.test.example";
     private static final String TEST_FQDN = "test.com";
     private static final String TEST_PROVIDER_NAME = "test";
+    private static final int TEST_WIFI_TECHNOLOGY = WifiInfo.WIFI_TECHNOLOGY_11AC;
 
     /**
      *  Verify parcel write/read with WifiInfo.
@@ -54,6 +55,7 @@
         writeWifiInfo.setFQDN(TEST_FQDN);
         writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
         writeWifiInfo.setNetworkSuggestionOrSpecifierPackageName(TEST_PACKAGE_NAME);
+        writeWifiInfo.setWifiTechnology(TEST_WIFI_TECHNOLOGY);
 
         Parcel parcel = Parcel.obtain();
         writeWifiInfo.writeToParcel(parcel, 0);
@@ -72,5 +74,6 @@
         assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getNetworkSuggestionOrSpecifierPackageName());
         assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
         assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
+        assertEquals(TEST_WIFI_TECHNOLOGY, readWifiInfo.getWifiTechnology());
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 885139b..881dcbb 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -59,6 +59,7 @@
 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 import android.net.wifi.WifiManager.OnWifiUsabilityStatsListener;
+import android.net.wifi.WifiManager.ScanResultsListener;
 import android.net.wifi.WifiManager.SoftApCallback;
 import android.net.wifi.WifiManager.TrafficStateCallback;
 import android.os.Binder;
@@ -102,13 +103,14 @@
     android.net.wifi.IWifiManager mWifiService;
     @Mock ApplicationInfo mApplicationInfo;
     @Mock WifiConfiguration mApConfig;
-    @Mock IBinder mAppBinder;
     @Mock SoftApCallback mSoftApCallback;
     @Mock TrafficStateCallback mTrafficStateCallback;
     @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
     @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
+    @Mock ScanResultsListener mScanResultListener;
+    @Mock Executor mCallbackExecutor;
+    @Mock Executor mExecutor;
 
-    private Executor mExecutor;
     private Handler mHandler;
     private TestLooper mLooper;
     private WifiManager mWifiManager;
@@ -1487,6 +1489,16 @@
     }
 
     /**
+     * Test behavior of {@link WifiManager#allowAutojoin(int, boolean)}
+     * @throws Exception
+     */
+    @Test
+    public void testAllowAutojoin() throws Exception {
+        mWifiManager.allowAutojoin(1, true);
+        verify(mWifiService).allowAutojoin(eq(1), eq(true));
+    }
+
+    /**
      * Test behavior of {@link WifiManager#disconnect()}
      * @throws Exception
      */
@@ -1711,4 +1723,66 @@
         mLooper.dispatchAll();
         verify(externalListener).onFailure(WifiManager.BUSY);
     }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if listener is not provided.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddScanResultsListenerWithNullListener() throws Exception {
+        mWifiManager.addScanResultsListener(mCallbackExecutor, null);
+    }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if executor is not provided.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddScanResultsListenerWithNullExecutor() throws Exception {
+        mWifiManager.addScanResultsListener(null, mScanResultListener);
+    }
+
+    /**
+     * Verify client provided listener is being called to the right listener.
+     */
+    @Test
+    public void testAddScanResultsListenerAndReceiveEvent() throws Exception {
+        ArgumentCaptor<IScanResultsListener.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(IScanResultsListener.Stub.class);
+        Executor executor = new SynchronousExecutor();
+        mWifiManager.addScanResultsListener(executor, mScanResultListener);
+        verify(mWifiService).registerScanResultsListener(any(IBinder.class),
+                callbackCaptor.capture(), anyInt());
+        callbackCaptor.getValue().onScanResultsAvailable();
+        verify(mScanResultListener).onScanResultsAvailable();
+    }
+
+    /**
+     * Verify client provided listener is being called on the right executor.
+     */
+    @Test
+    public void testAddScanResultsListenerWithTheTargetExecutor() throws Exception {
+        ArgumentCaptor<IScanResultsListener.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(IScanResultsListener.Stub.class);
+        mWifiManager.addScanResultsListener(mExecutor, mScanResultListener);
+        verify(mWifiService).registerScanResultsListener(any(IBinder.class),
+                callbackCaptor.capture(), anyInt());
+        callbackCaptor.getValue().onScanResultsAvailable();
+        verify(mExecutor).execute(any(Runnable.class));
+    }
+
+    /**
+     * Verify client removeScanResultsListener.
+     */
+    @Test
+    public void testRemoveScanResultsListener() throws Exception {
+        mWifiManager.removeScanResultsListener(mScanResultListener);
+        verify(mWifiService).unregisterScanResultsListener(anyInt());
+    }
+
+    /**
+     * Verify client removeScanResultsListener with null listener will cause an exception.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testRemoveScanResultsListenerWithNullListener() throws Exception {
+        mWifiManager.removeScanResultsListener(null);
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 4dfa96b..6990089 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.*;
 
 import android.net.MacAddress;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.PasspointTestUtils;
 import android.os.Parcel;
 import android.os.Process;
 
@@ -39,6 +41,7 @@
     private static final String TEST_BSSID = "12:12:12:12:12:12";
     private static final String TEST_SSID_1 = "\"Test1234\"";
     private static final String TEST_PRESHARED_KEY = "Test123";
+    private static final String TEST_FQDN = "fqdn";
 
     /**
      * Validate correctness of WifiNetworkSuggestion object created by
@@ -186,6 +189,25 @@
     }
 
     /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for Passpoint network which requires
+     *  app interaction and metered.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForPasspointNetworkWithReqAppInteractionMetered() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .setIsAppInteractionRequired(true)
+                .setIsMetered(true)
+                .build();
+        assertEquals(TEST_FQDN, suggestion.wifiConfiguration.FQDN);
+        assertTrue(suggestion.isAppInteractionRequired);
+        assertEquals(suggestion.wifiConfiguration.meteredOverride,
+                WifiConfiguration.METERED_OVERRIDE_METERED);
+    }
+
+    /**
      * Ensure {@link WifiNetworkSuggestion.Builder#setSsid(String)} throws an exception
      * when the string is not Unicode.
      */
@@ -209,6 +231,18 @@
     }
 
     /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)}}
+     * throws an exception when the PasspointConfiguration is not valid.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSuggestionBuilderSetPasspointConfigWithNonValid() {
+        PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
+        new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
      * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
      * when {@link WifiNetworkSuggestion.Builder#setSsid(String)} is not set.
      */
@@ -311,6 +345,91 @@
     }
 
     /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setSsid(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothSsidAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa2Passphrase(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothWpa2PassphraseAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothWpa3PassphraseAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)}
+     * and {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are
+     * invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothEnterpriseAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setIsEnhancedOpen(boolean)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothEnhancedOpenAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setIsEnhancedOpen(true)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setIsHiddenSsid(boolean)} and
+     * {@link WifiNetworkSuggestion.Builder#setPasspointConfig(PasspointConfiguration)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothHiddenSsidAndPasspointConfig() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        new WifiNetworkSuggestion.Builder()
+                .setIsHiddenSsid(true)
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+    }
+
+    /**
      * Check that parcel marshalling/unmarshalling works
      */
     @Test
@@ -319,8 +438,8 @@
         configuration.SSID = TEST_SSID;
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
-        WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, true, TEST_UID, TEST_PACKAGE_NAME);
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
+                configuration, null, false, true, TEST_UID, TEST_PACKAGE_NAME);
 
         Parcel parcelW = Parcel.obtain();
         suggestion.writeToParcel(parcelW, 0);
@@ -337,6 +456,39 @@
         // SSID + keyMgmt + same UID). |isAppInteractionRequired| & |isUserInteractionRequired| are
         // not considered for equality and hence needs to be checked for explicitly below.
         assertEquals(suggestion, parcelSuggestion);
+        assertEquals(suggestion.hashCode(), parcelSuggestion.hashCode());
+        assertEquals(suggestion.isAppInteractionRequired,
+                parcelSuggestion.isAppInteractionRequired);
+        assertEquals(suggestion.isUserInteractionRequired,
+                parcelSuggestion.isUserInteractionRequired);
+    }
+
+    /**
+     * Check that parcel marshalling/unmarshalling works
+     */
+    @Test
+    public void testPasspointNetworkSuggestionParcel() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+
+        Parcel parcelW = Parcel.obtain();
+        suggestion.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        WifiNetworkSuggestion parcelSuggestion =
+                WifiNetworkSuggestion.CREATOR.createFromParcel(parcelR);
+
+        // Two suggestion objects are considered equal if they point to the same network (i.e same
+        // SSID + keyMgmt + same UID). |isAppInteractionRequired| & |isUserInteractionRequired| are
+        // not considered for equality and hence needs to be checked for explicitly below.
+        assertEquals(suggestion, parcelSuggestion);
+        assertEquals(suggestion.hashCode(), parcelSuggestion.hashCode());
         assertEquals(suggestion.isAppInteractionRequired,
                 parcelSuggestion.isAppInteractionRequired);
         assertEquals(suggestion.isUserInteractionRequired,
@@ -354,7 +506,7 @@
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, true, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, true, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
@@ -362,10 +514,11 @@
         configuration1.BSSID = TEST_BSSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, true, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, true, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertEquals(suggestion, suggestion1);
+        assertEquals(suggestion.hashCode(), suggestion1.hashCode());
     }
 
     /**
@@ -378,14 +531,14 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID_1;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -402,14 +555,14 @@
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null,  false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -425,14 +578,14 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration1, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -448,11 +601,11 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID,
                         TEST_PACKAGE_NAME);
 
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID_OTHER,
+                new WifiNetworkSuggestion(configuration, null, false, false, TEST_UID_OTHER,
                         TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
@@ -467,13 +620,48 @@
         WifiConfiguration configuration = new WifiConfiguration();
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
-        WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID, TEST_PACKAGE_NAME);
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
+                configuration, null, false, false, TEST_UID, TEST_PACKAGE_NAME);
 
-        WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
-                        TEST_PACKAGE_NAME_OTHER);
+        WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion(
+                configuration, null, false, false, TEST_UID, TEST_PACKAGE_NAME_OTHER);
 
         assertNotEquals(suggestion, suggestion1);
     }
+    /**
+     * Check NetworkSuggestion equals returns {@code true} for 2 Passpoint network suggestions with
+     * same FQDN.
+     */
+    @Test
+    public void testPasspointNetworkSuggestionEqualsSameWithSameFQDN() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        PasspointConfiguration passpointConfiguration1 = PasspointTestUtils.createConfig();
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+        WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration1)
+                .build();
+        assertEquals(suggestion, suggestion1);
+        assertEquals(suggestion.hashCode(), suggestion1.hashCode());
+    }
+
+    /**
+     * Check NetworkSuggestion equals returns {@code false} for 2 Passpoint network suggestions with
+     * different FQDN.
+     */
+    @Test
+    public void testPasspointNetworkSuggestionNotEqualsSameWithDifferentFQDN() {
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        PasspointConfiguration passpointConfiguration1 = PasspointTestUtils.createConfig();
+        passpointConfiguration1.getHomeSp().setFqdn(TEST_FQDN + 1);
+
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .build();
+        WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration1)
+                .build();
+        assertNotEquals(suggestion, suggestion1);
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
index d9a1d9af..439e672 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/ConfigParserTest.java
@@ -54,6 +54,8 @@
             "assets/hsr1/HSR1ProfileWithInvalidContentType.base64";
     private static final String PASSPOINT_INSTALLATION_FILE_WITHOUT_PROFILE =
             "assets/hsr1/HSR1ProfileWithoutProfile.base64";
+    private static final String PASSPOINT_INSTALLATION_FILE_WITH_UPDATE_ID =
+            "assets/hsr1/HSR1ProfileWithUpdateIdentifier.base64";
 
     /**
      * Read the content of the given resource file into a String.
@@ -85,17 +87,17 @@
 
         // HomeSP configuration.
         HomeSp homeSp = new HomeSp();
-        homeSp.setFriendlyName("Century House");
-        homeSp.setFqdn("mi6.co.uk");
+        homeSp.setFriendlyName("Example Network");
+        homeSp.setFqdn("hotspot.example.net");
         homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L});
         config.setHomeSp(homeSp);
 
         // Credential configuration.
         Credential credential = new Credential();
-        credential.setRealm("shaken.stirred.com");
+        credential.setRealm("example.com");
         Credential.UserCredential userCredential = new Credential.UserCredential();
-        userCredential.setUsername("james");
-        userCredential.setPassword("Ym9uZDAwNw==");
+        userCredential.setUsername("user");
+        userCredential.setPassword("cGFzc3dvcmQ=");
         userCredential.setEapType(21);
         userCredential.setNonEapInnerMethod("MS-CHAP-V2");
         credential.setUserCredential(userCredential);
@@ -106,8 +108,8 @@
         certCredential.setCertSha256Fingerprint(certSha256Fingerprint);
         credential.setCertCredential(certCredential);
         Credential.SimCredential simCredential = new Credential.SimCredential();
-        simCredential.setImsi("imsi");
-        simCredential.setEapType(24);
+        simCredential.setImsi("123456*");
+        simCredential.setEapType(23);
         credential.setSimCredential(simCredential);
         credential.setCaCertificate(FakeKeys.CA_CERT0);
         config.setCredential(credential);
@@ -201,4 +203,21 @@
         assertNull(ConfigParser.parsePasspointConfig(
                 "application/x-wifi-config", configStr.getBytes()));
     }
+
+    /**
+     * Verify a valid installation file is parsed successfully with the matching contents, and that
+     * Update identifier is cleared.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFileWithUpdateIdentifier() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_UPDATE_ID);
+        PasspointConfiguration expectedConfig = generateConfigurationFromProfile();
+        PasspointConfiguration actualConfig =
+                ConfigParser.parsePasspointConfig(
+                        "application/x-wifi-config", configStr.getBytes());
+        // Expected configuration does not contain an update identifier
+        assertTrue(actualConfig.equals(expectedConfig));
+    }
 }
\ No newline at end of file
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 88740d8..f501b16 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -19,23 +19,15 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.net.wifi.EAPConstants;
-import android.net.wifi.hotspot2.pps.Credential;
-import android.net.wifi.hotspot2.pps.HomeSp;
-import android.net.wifi.hotspot2.pps.Policy;
-import android.net.wifi.hotspot2.pps.UpdateParameter;
 import android.os.Parcel;
-import android.util.Base64;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -47,136 +39,6 @@
     private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
 
     /**
-     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
-     *
-     * @return {@link android.net.wifi.hotspot2.pps.HomeSP}
-     */
-    private static HomeSp createHomeSp() {
-        HomeSp homeSp = new HomeSp();
-        homeSp.setFqdn("fqdn");
-        homeSp.setFriendlyName("friendly name");
-        homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
-        return homeSp;
-    }
-
-    /**
-     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.Credential}.
-     *
-     * @return {@link android.net.wifi.hotspot2.pps.Credential}
-     */
-    private static Credential createCredential() {
-        Credential cred = new Credential();
-        cred.setRealm("realm");
-        cred.setUserCredential(null);
-        cred.setCertCredential(null);
-        cred.setSimCredential(new Credential.SimCredential());
-        cred.getSimCredential().setImsi("1234*");
-        cred.getSimCredential().setEapType(EAPConstants.EAP_SIM);
-        cred.setCaCertificate(null);
-        cred.setClientCertificateChain(null);
-        cred.setClientPrivateKey(null);
-        return cred;
-    }
-
-    /**
-     * Helper function for creating a {@link Policy} for testing.
-     *
-     * @return {@link Policy}
-     */
-    private static Policy createPolicy() {
-        Policy policy = new Policy();
-        policy.setMinHomeDownlinkBandwidth(123);
-        policy.setMinHomeUplinkBandwidth(345);
-        policy.setMinRoamingDownlinkBandwidth(567);
-        policy.setMinRoamingUplinkBandwidth(789);
-        policy.setMaximumBssLoadValue(12);
-        policy.setExcludedSsidList(new String[] {"ssid1", "ssid2"});
-        HashMap<Integer, String> requiredProtoPortMap = new HashMap<>();
-        requiredProtoPortMap.put(12, "23,342,123");
-        requiredProtoPortMap.put(23, "789,372,1235");
-        policy.setRequiredProtoPortMap(requiredProtoPortMap);
-
-        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
-        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
-        partner1.setFqdn("partner1.com");
-        partner1.setFqdnExactMatch(true);
-        partner1.setPriority(12);
-        partner1.setCountries("us,jp");
-        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
-        partner2.setFqdn("partner2.com");
-        partner2.setFqdnExactMatch(false);
-        partner2.setPriority(42);
-        partner2.setCountries("ca,fr");
-        preferredRoamingPartnerList.add(partner1);
-        preferredRoamingPartnerList.add(partner2);
-        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
-
-        UpdateParameter policyUpdate = new UpdateParameter();
-        policyUpdate.setUpdateIntervalInMinutes(1712);
-        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
-        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
-        policyUpdate.setServerUri("policy.update.com");
-        policyUpdate.setUsername("username");
-        policyUpdate.setBase64EncodedPassword(
-                Base64.encodeToString("password".getBytes(), Base64.DEFAULT));
-        policyUpdate.setTrustRootCertUrl("trust.cert.com");
-        policyUpdate.setTrustRootCertSha256Fingerprint(
-                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        policy.setPolicyUpdate(policyUpdate);
-
-        return policy;
-    }
-
-    private static UpdateParameter createSubscriptionUpdate() {
-        UpdateParameter subUpdate = new UpdateParameter();
-        subUpdate.setUpdateIntervalInMinutes(9021);
-        subUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
-        subUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
-        subUpdate.setServerUri("subscription.update.com");
-        subUpdate.setUsername("subUsername");
-        subUpdate.setBase64EncodedPassword(
-                Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT));
-        subUpdate.setTrustRootCertUrl("subscription.trust.cert.com");
-        subUpdate.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        return subUpdate;
-    }
-    /**
-     * Helper function for creating a {@link PasspointConfiguration} for testing.
-     *
-     * @return {@link PasspointConfiguration}
-     */
-    private static PasspointConfiguration createConfig() {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.setUpdateIdentifier(1234);
-        config.setHomeSp(createHomeSp());
-        config.setAaaServerTrustedNames(
-                new String[] {"trusted.fqdn.com", "another-trusted.fqdn.com"});
-        config.setCredential(createCredential());
-        config.setPolicy(createPolicy());
-        config.setSubscriptionUpdate(createSubscriptionUpdate());
-        Map<String, byte[]> trustRootCertList = new HashMap<>();
-        trustRootCertList.put("trustRoot.cert1.com",
-                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        trustRootCertList.put("trustRoot.cert2.com",
-                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
-        config.setTrustRootCertList(trustRootCertList);
-        config.setUpdateIdentifier(1);
-        config.setCredentialPriority(120);
-        config.setSubscriptionCreationTimeInMillis(231200);
-        config.setSubscriptionExpirationTimeInMillis(2134232);
-        config.setSubscriptionType("Gold");
-        config.setUsageLimitUsageTimePeriodInMinutes(3600);
-        config.setUsageLimitStartTimeInMillis(124214213);
-        config.setUsageLimitDataLimit(14121);
-        config.setUsageLimitTimeLimitInMinutes(78912);
-        Map<String, String> friendlyNames = new HashMap<>();
-        friendlyNames.put("en", "ServiceName1");
-        friendlyNames.put("kr", "ServiceName2");
-        config.setServiceFriendlyNames(friendlyNames);
-        return config;
-    }
-
-    /**
      * Verify parcel write and read consistency for the given configuration.
      *
      * @param writeConfig The configuration to verify
@@ -209,7 +71,7 @@
      */
     @Test
     public void verifyParcelWithFullConfiguration() throws Exception {
-        verifyParcel(createConfig());
+        verifyParcel(PasspointTestUtils.createConfig());
     }
 
     /**
@@ -219,7 +81,7 @@
      */
     @Test
     public void verifyParcelWithoutServiceNames() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setServiceFriendlyNames(null);
         verifyParcel(config);
     }
@@ -231,7 +93,7 @@
      */
     @Test
     public void verifyParcelWithoutHomeSP() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setHomeSp(null);
         verifyParcel(config);
     }
@@ -243,7 +105,7 @@
      */
     @Test
     public void verifyParcelWithoutCredential() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setCredential(null);
         verifyParcel(config);
     }
@@ -255,7 +117,7 @@
      */
     @Test
     public void verifyParcelWithoutPolicy() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setPolicy(null);
         verifyParcel(config);
     }
@@ -267,7 +129,7 @@
      */
     @Test
     public void verifyParcelWithoutSubscriptionUpdate() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setSubscriptionUpdate(null);
         verifyParcel(config);
     }
@@ -280,7 +142,7 @@
      */
     @Test
     public void verifyParcelWithoutTrustRootCertList() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setTrustRootCertList(null);
         verifyParcel(config);
     }
@@ -293,7 +155,7 @@
      */
     @Test
     public void verifyParcelWithoutAaaServerTrustedNames() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setAaaServerTrustedNames(null);
         verifyParcel(config);
     }
@@ -318,10 +180,10 @@
      */
     @Test
     public void validateFullConfig() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
 
         assertTrue(config.validate());
-        assertTrue(config.validateForR2());
+        assertFalse(config.isOsuProvisioned());
     }
 
     /**
@@ -332,7 +194,7 @@
      */
     @Test
     public void validateFullConfigWithoutUpdateIdentifier() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setUpdateIdentifier(Integer.MIN_VALUE);
 
         assertTrue(config.validate());
@@ -346,7 +208,7 @@
      */
     @Test
     public void validateConfigWithoutCredential() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setCredential(null);
 
         assertFalse(config.validate());
@@ -360,7 +222,7 @@
      */
     @Test
     public void validateConfigWithoutHomeSp() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setHomeSp(null);
 
         assertFalse(config.validate());
@@ -375,11 +237,10 @@
      */
     @Test
     public void validateConfigWithoutPolicy() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setPolicy(null);
 
         assertTrue(config.validate());
-        assertTrue(config.validateForR2());
     }
 
     /**
@@ -390,7 +251,7 @@
      */
     @Test
     public void validateConfigWithoutSubscriptionUpdate() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setSubscriptionUpdate(null);
 
         assertTrue(config.validate());
@@ -405,11 +266,10 @@
      */
     @Test
     public void validateConfigWithoutAaaServerTrustedNames() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setAaaServerTrustedNames(null);
 
         assertTrue(config.validate());
-        assertTrue(config.validateForR2());
     }
 
     /**
@@ -420,7 +280,7 @@
      */
     @Test
     public void validateConfigWithInvalidTrustRootCertUrl() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         byte[] rawUrlBytes = new byte[MAX_URL_BYTES + 1];
         Map<String, byte[]> trustRootCertList = new HashMap<>();
         Arrays.fill(rawUrlBytes, (byte) 'a');
@@ -445,7 +305,7 @@
      */
     @Test
     public void validateConfigWithInvalidTrustRootCertFingerprint() throws Exception {
-        PasspointConfiguration config = createConfig();
+        PasspointConfiguration config = PasspointTestUtils.createConfig();
         Map<String, byte[]> trustRootCertList = new HashMap<>();
         trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES + 1]);
         config.setTrustRootCertList(trustRootCertList);
@@ -482,8 +342,21 @@
      */
     @Test
     public void validateCopyConstructorWithValidSource() throws Exception {
-        PasspointConfiguration sourceConfig = createConfig();
+        PasspointConfiguration sourceConfig = PasspointTestUtils.createConfig();
         PasspointConfiguration copyConfig = new PasspointConfiguration(sourceConfig);
         assertTrue(copyConfig.equals(sourceConfig));
     }
+
+    /**
+     * Verify that a configuration containing all fields is valid for R2.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateFullR2Config() throws Exception {
+        PasspointConfiguration config = PasspointTestUtils.createR2Config();
+        assertTrue(config.validate());
+        assertTrue(config.validateForR2());
+        assertTrue(config.isOsuProvisioned());
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java
new file mode 100644
index 0000000..8d55acb
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointTestUtils.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.hotspot2;
+
+import android.net.wifi.EAPConstants;
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.net.wifi.hotspot2.pps.Policy;
+import android.net.wifi.hotspot2.pps.UpdateParameter;
+import android.util.Base64;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PasspointTestUtils {
+    private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
+
+    /**
+     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
+     *
+     * @return {@link android.net.wifi.hotspot2.pps.HomeSP}
+     */
+    private static HomeSp createHomeSp() {
+        HomeSp homeSp = new HomeSp();
+        homeSp.setFqdn("fqdn");
+        homeSp.setFriendlyName("friendly name");
+        homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
+        return homeSp;
+    }
+
+    /**
+     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.Credential}.
+     *
+     * @return {@link android.net.wifi.hotspot2.pps.Credential}
+     */
+    private static Credential createCredential() {
+        Credential cred = new Credential();
+        cred.setRealm("realm");
+        cred.setUserCredential(null);
+        cred.setCertCredential(null);
+        cred.setSimCredential(new Credential.SimCredential());
+        cred.getSimCredential().setImsi("1234*");
+        cred.getSimCredential().setEapType(EAPConstants.EAP_SIM);
+        cred.setCaCertificate(null);
+        cred.setClientCertificateChain(null);
+        cred.setClientPrivateKey(null);
+        return cred;
+    }
+
+    /**
+     * Helper function for creating a {@link Policy} for testing.
+     *
+     * @return {@link Policy}
+     */
+    private static Policy createPolicy() {
+        Policy policy = new Policy();
+        policy.setMinHomeDownlinkBandwidth(123);
+        policy.setMinHomeUplinkBandwidth(345);
+        policy.setMinRoamingDownlinkBandwidth(567);
+        policy.setMinRoamingUplinkBandwidth(789);
+        policy.setMaximumBssLoadValue(12);
+        policy.setExcludedSsidList(new String[] {"ssid1", "ssid2"});
+        HashMap<Integer, String> requiredProtoPortMap = new HashMap<>();
+        requiredProtoPortMap.put(12, "23,342,123");
+        requiredProtoPortMap.put(23, "789,372,1235");
+        policy.setRequiredProtoPortMap(requiredProtoPortMap);
+
+        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
+        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
+        partner1.setFqdn("partner1.com");
+        partner1.setFqdnExactMatch(true);
+        partner1.setPriority(12);
+        partner1.setCountries("us,jp");
+        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
+        partner2.setFqdn("partner2.com");
+        partner2.setFqdnExactMatch(false);
+        partner2.setPriority(42);
+        partner2.setCountries("ca,fr");
+        preferredRoamingPartnerList.add(partner1);
+        preferredRoamingPartnerList.add(partner2);
+        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
+
+        UpdateParameter policyUpdate = new UpdateParameter();
+        policyUpdate.setUpdateIntervalInMinutes(1712);
+        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
+        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
+        policyUpdate.setServerUri("policy.update.com");
+        policyUpdate.setUsername("username");
+        policyUpdate.setBase64EncodedPassword(
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT));
+        policyUpdate.setTrustRootCertUrl("trust.cert.com");
+        policyUpdate.setTrustRootCertSha256Fingerprint(
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        policy.setPolicyUpdate(policyUpdate);
+
+        return policy;
+    }
+
+    private static UpdateParameter createSubscriptionUpdate() {
+        UpdateParameter subUpdate = new UpdateParameter();
+        subUpdate.setUpdateIntervalInMinutes(9021);
+        subUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
+        subUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
+        subUpdate.setServerUri("subscription.update.com");
+        subUpdate.setUsername("subUsername");
+        subUpdate.setBase64EncodedPassword(
+                Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT));
+        subUpdate.setTrustRootCertUrl("subscription.trust.cert.com");
+        subUpdate.setTrustRootCertSha256Fingerprint(new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        return subUpdate;
+    }
+    /**
+     * Helper function for creating a {@link PasspointConfiguration} for testing.
+     *
+     * @return {@link PasspointConfiguration}
+     */
+    public static PasspointConfiguration createConfig() {
+        PasspointConfiguration config = new PasspointConfiguration();
+        config.setHomeSp(createHomeSp());
+        config.setAaaServerTrustedNames(
+                new String[] {"trusted.fqdn.com", "another-trusted.fqdn.com"});
+        config.setCredential(createCredential());
+        config.setPolicy(createPolicy());
+        config.setSubscriptionUpdate(createSubscriptionUpdate());
+        Map<String, byte[]> trustRootCertList = new HashMap<>();
+        trustRootCertList.put("trustRoot.cert1.com",
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        trustRootCertList.put("trustRoot.cert2.com",
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        config.setTrustRootCertList(trustRootCertList);
+        config.setCredentialPriority(120);
+        config.setSubscriptionCreationTimeInMillis(231200);
+        config.setSubscriptionExpirationTimeInMillis(2134232);
+        config.setSubscriptionType("Gold");
+        config.setUsageLimitUsageTimePeriodInMinutes(3600);
+        config.setUsageLimitStartTimeInMillis(124214213);
+        config.setUsageLimitDataLimit(14121);
+        config.setUsageLimitTimeLimitInMinutes(78912);
+        Map<String, String> friendlyNames = new HashMap<>();
+        friendlyNames.put("en", "ServiceName1");
+        friendlyNames.put("kr", "ServiceName2");
+        config.setServiceFriendlyNames(friendlyNames);
+        return config;
+    }
+
+    /**
+     * Helper function for creating an R2 {@link PasspointConfiguration} for testing.
+     *
+     * @return {@link PasspointConfiguration}
+     */
+    public static PasspointConfiguration createR2Config() {
+        PasspointConfiguration config = createConfig();
+        config.setUpdateIdentifier(1234);
+        return config;
+    }
+}